﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область ПрограммныйИнтерфейс

// Устанавливает заголовок главного окна приложения, используя значение константы
// ЗаголовокПриложения и заголовок приложения по умолчанию.
//
// Параметры:
//   ПриЗапуске - Булево - Истина, если вызывается при начале работы программы.
//
Процедура УстановитьРасширенныйЗаголовокПриложения(ПриЗапуске = Ложь) Экспорт
	
	ПараметрыКлиента = ?(ПриЗапуске, ПараметрыРаботыКлиентаПриЗапуске(),
		ПараметрыРаботыКлиента());
		
	Если ОбщегоНазначенияКлиент.ДоступноИспользованиеРазделенныхДанных() Тогда
		ПредставлениеЗаголовка = ПараметрыКлиента.ЗаголовокПриложения;
		ПредставлениеКонфигурации = ПараметрыКлиента.ПодробнаяИнформация;
		
		Если ПустаяСтрока(СокрЛП(ПредставлениеЗаголовка)) Тогда
			Если ПараметрыКлиента.Свойство("ПредставлениеОбластиДанных") Тогда
				ШаблонЗаголовка = "%1 / %2";
				ЗаголовокПриложения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонЗаголовка, ПараметрыКлиента.ПредставлениеОбластиДанных,
					ПредставлениеКонфигурации);
			Иначе
				ШаблонЗаголовка = "%1";
				ЗаголовокПриложения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонЗаголовка, ПредставлениеКонфигурации);
			КонецЕсли;
		Иначе
			ШаблонЗаголовка = "%1 / %2";
			ЗаголовокПриложения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонЗаголовка,
				СокрЛП(ПредставлениеЗаголовка), ПредставлениеКонфигурации);
		КонецЕсли;
	Иначе
		ШаблонЗаголовка = "%1 / %2";
		ЗаголовокПриложения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонЗаголовка, НСтр("ru = 'Не установлены разделители'"), ПараметрыКлиента.ПодробнаяИнформация);
	КонецЕсли;
	
	Если Не ОбщегоНазначенияКлиент.РазделениеВключено()
	   И ПараметрыКлиента.Свойство("РаботаСВнешнимиРесурсамиЗаблокирована") Тогда
		ЗаголовокПриложения = "[" + НСтр("ru = 'КОПИЯ'") + "]" + " " + ЗаголовокПриложения;
	КонецЕсли;
	
	ОбщегоНазначенияКлиентПереопределяемый.ПриУстановкеЗаголовкаКлиентскогоПриложения(ЗаголовокПриложения, ПриЗапуске);
	
	КлиентскоеПриложение.УстановитьЗаголовок(ЗаголовокПриложения);
	
КонецПроцедуры

// Показать форму вопроса.
//
// Параметры:
//   ОписаниеОповещенияОЗавершении - ОписаниеОповещения - описание процедуры, которая будет вызвана после закрытия окна
//                                                        вопроса со следующими параметрами:
//                                                          РезультатВопроса - Структура:
//                                                            Значение - результат выбора пользователя: значение
//                                                                       системного перечисления или значение,
//                                                                       связанное с нажатой кнопкой. В случае закрытия
//                                                                       диалога по истечении времени - значение
//                                                                       Таймаут.
//                                                            БольшеНеЗадаватьЭтотВопрос - Булево - результат выбора
//                                                                                                  пользователя в
//                                                                                                  одноименном флажке.
//                                                          ДополнительныеПараметры - Структура 
//   ТекстВопроса                  - Строка, ФорматированнаяСтрока - текст задаваемого вопроса. 
//   Кнопки                        - РежимДиалогаВопрос
//                                 - СписокЗначений     - может быть задан список значений, в котором:
//                                       Значение - содержит значение, связанное с кнопкой и возвращаемое при 
//                                                  ее нажатии. В качестве значения может использоваться значение
//                                                  перечисления КодВозвратаДиалога, а также другие значения,
//                                                  поддерживающее XDTO-сериализацию.
//                                       Представление - текст кнопки.
//
//   ДополнительныеПараметры       - см. СтандартныеПодсистемыКлиент.ПараметрыВопросаПользователю.
//
Процедура ПоказатьВопросПользователю(ОписаниеОповещенияОЗавершении, ТекстВопроса, Кнопки, ДополнительныеПараметры = Неопределено) Экспорт
	
	Параметры = ПараметрыВопросаПользователю();
	Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда
		ЗаполнитьЗначенияСвойств(Параметры, ДополнительныеПараметры);
	КонецЕсли;
	
	КодыВозвратаДиалога = Новый Соответствие;
	КодыВозвратаДиалога.Вставить(КодВозвратаДиалога.Да, "КодВозвратаДиалога.Да");
	КодыВозвратаДиалога.Вставить(КодВозвратаДиалога.Нет, "КодВозвратаДиалога.Нет");
	КодыВозвратаДиалога.Вставить(КодВозвратаДиалога.ОК, "КодВозвратаДиалога.ОК");
	КодыВозвратаДиалога.Вставить(КодВозвратаДиалога.Отмена, "КодВозвратаДиалога.Отмена");
	КодыВозвратаДиалога.Вставить(КодВозвратаДиалога.Повторить, "КодВозвратаДиалога.Повторить");
	КодыВозвратаДиалога.Вставить(КодВозвратаДиалога.Прервать, "КодВозвратаДиалога.Прервать");
	КодыВозвратаДиалога.Вставить(КодВозвратаДиалога.Пропустить, "КодВозвратаДиалога.Пропустить");
	КодыВозвратаДиалога.Вставить(КодВозвратаДиалога.Таймаут, "КодВозвратаДиалога.Таймаут");
	
	ПредставленияКнопок = Новый Соответствие;
	ПредставленияКнопок.Вставить(КодВозвратаДиалога.Да, НСтр("ru = 'Да'"));
	ПредставленияКнопок.Вставить(КодВозвратаДиалога.Нет, НСтр("ru = 'Нет'"));
	ПредставленияКнопок.Вставить(КодВозвратаДиалога.ОК, НСтр("ru = 'ОК'"));
	ПредставленияКнопок.Вставить(КодВозвратаДиалога.Отмена, НСтр("ru = 'Отмена'"));
	ПредставленияКнопок.Вставить(КодВозвратаДиалога.Повторить, НСтр("ru = 'Повторить'"));
	ПредставленияКнопок.Вставить(КодВозвратаДиалога.Прервать, НСтр("ru = 'Прервать'"));
	ПредставленияКнопок.Вставить(КодВозвратаДиалога.Пропустить, НСтр("ru = 'Пропустить'"));
	ПредставленияКнопок.Вставить(КодВозвратаДиалога.Таймаут, НСтр("ru = 'Таймаут'"));
	
	РежимыДиалогаВопрос = Новый Соответствие;
	РежимыДиалогаВопрос.Вставить(РежимДиалогаВопрос.ДаНет, "РежимДиалогаВопрос.ДаНет");
	РежимыДиалогаВопрос.Вставить(РежимДиалогаВопрос.ДаНетОтмена, "РежимДиалогаВопрос.ДаНетОтмена");
	РежимыДиалогаВопрос.Вставить(РежимДиалогаВопрос.ОК, "РежимДиалогаВопрос.ОК");
	РежимыДиалогаВопрос.Вставить(РежимДиалогаВопрос.ОКОтмена, "РежимДиалогаВопрос.ОКОтмена");
	РежимыДиалогаВопрос.Вставить(РежимДиалогаВопрос.ПовторитьОтмена, "РежимДиалогаВопрос.ПовторитьОтмена");
	РежимыДиалогаВопрос.Вставить(РежимДиалогаВопрос.ПрерватьПовторитьПропустить, "РежимДиалогаВопрос.ПрерватьПовторитьПропустить");
	
	КнопкиДиалога = Кнопки;
	
	Если ТипЗнч(Кнопки) = Тип("СписокЗначений") Тогда
		КнопкиДиалога = ОбщегоНазначенияКлиент.СкопироватьРекурсивно(Кнопки);
		Для Каждого Кнопка Из КнопкиДиалога Цикл
			Если Кнопка.Представление = "" Тогда
				Кнопка.Представление = ПредставленияКнопок[Кнопка.Значение];
			КонецЕсли;
			Если ТипЗнч(Кнопка.Значение) = Тип("КодВозвратаДиалога") Тогда
				Кнопка.Значение = КодыВозвратаДиалога[Кнопка.Значение];
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Если ТипЗнч(Кнопки) = Тип("РежимДиалогаВопрос") Тогда
		КнопкиДиалога = РежимыДиалогаВопрос[Кнопки];
	КонецЕсли;
	
	Если ТипЗнч(Параметры.КнопкаПоУмолчанию) = Тип("КодВозвратаДиалога") Тогда
		Параметры.КнопкаПоУмолчанию = КодыВозвратаДиалога[Параметры.КнопкаПоУмолчанию];
	КонецЕсли;
	
	Если ТипЗнч(Параметры.КнопкаТаймаута) = Тип("КодВозвратаДиалога") Тогда
		Параметры.КнопкаТаймаута = КодыВозвратаДиалога[Параметры.КнопкаТаймаута];
	КонецЕсли;
	
	Параметры.Вставить("Кнопки", КнопкиДиалога);
	Параметры.Вставить("ТекстСообщения", ТекстВопроса);
	
	ОткрытьФорму("ОбщаяФорма.Вопрос", Параметры, , , , , ОписаниеОповещенияОЗавершении);
	
КонецПроцедуры

// Возвращает новую структуру дополнительных параметров для процедуры ПоказатьВопросПользователю.
//
// Возвращаемое значение:
//  Структура:
//    * КнопкаПоУмолчанию             - Произвольный - определяет кнопку по умолчанию по типу кнопки или по связанному
//                                                     с ней значению.
//    * Таймаут                       - Число        - интервал времени в секундах до автоматического закрытия окна
//                                                     вопроса.
//    * КнопкаТаймаута                - Произвольный - кнопка (по типу кнопки или по связанному с ней значению), 
//                                                     на которой отображается количество секунд, оставшихся до
//                                                     истечения таймаута.
//    * Заголовок                     - Строка       - заголовок вопроса. 
//    * ПредлагатьБольшеНеЗадаватьЭтотВопрос - Булево - если Истина, то в окне вопроса будет доступен одноименный флажок.
//    * БольшеНеЗадаватьЭтотВопрос    - Булево       - принимает значение, выбранное пользователем в соответствующем
//                                                     флажке.
//    * БлокироватьВесьИнтерфейс      - Булево       - если Истина, форма вопроса открывается, блокируя работу всех
//                                                     остальных открытых окон, включая главное окно.
//    * Картинка                      - Картинка     - картинка, выводимая в окне вопроса.
//    * ТекстФлажка                   - Строка       - текст флажка "Больше не спрашивать".
//
Функция ПараметрыВопросаПользователю() Экспорт
	
	Параметры = Новый Структура;
	Параметры.Вставить("КнопкаПоУмолчанию", Неопределено);
	Параметры.Вставить("Таймаут", 0);
	Параметры.Вставить("КнопкаТаймаута", Неопределено);
	Параметры.Вставить("Заголовок", КлиентскоеПриложение.ПолучитьЗаголовок());
	Параметры.Вставить("ПредлагатьБольшеНеЗадаватьЭтотВопрос", Истина);
	Параметры.Вставить("БольшеНеЗадаватьЭтотВопрос", Ложь);
	Параметры.Вставить("БлокироватьВесьИнтерфейс", Ложь);
	Параметры.Вставить("Картинка", БиблиотекаКартинок.Вопрос32);
	Параметры.Вставить("ТекстФлажка", "");
	
	Возврат Параметры;
	
КонецФункции	

// Вызывается при необходимости открыть форму списка активных пользователей,
// которые в данный момент времени работают с системой.
//
// Параметры:
//    ПараметрыФормы - Структура        - см. описание параметра Параметры метода ОткрытьФорму в синтакс-помощнике.
//    ВладелецФормы  - ФормаКлиентскогоПриложения - см. описание параметра Владелец метода ОткрытьФорму в синтакс-помощнике.
//
Процедура ОткрытьСписокАктивныхПользователей(ПараметрыФормы = Неопределено, ВладелецФормы = Неопределено) Экспорт
	
	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.ЗавершениеРаботыПользователей") Тогда
		
		ИмяФормы = "";
		МодульСоединенияИБКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("СоединенияИБКлиент");
		МодульСоединенияИБКлиент.ПриОпределенииФормыАктивныхПользователей(ИмяФормы);
		ОткрытьФорму(ИмяФормы, ПараметрыФормы, ВладелецФормы);
		
	Иначе
		
		ПоказатьПредупреждение(,
			НСтр("ru = 'Для того чтобы открыть список активных пользователей, перейдите в меню
				       |Все функции - Стандартные - Активные пользователи.'"));
		
	КонецЕсли;
	
КонецПроцедуры

// См. СтандартныеПодсистемыСервер.ЭтоБазоваяВерсияКонфигурации
Функция ЭтоБазоваяВерсияКонфигурации() Экспорт
	
	Возврат ПараметрКлиента("ЭтоБазоваяВерсияКонфигурации");
	
КонецФункции

// См. СтандартныеПодсистемыСервер.ЭтоУчебнаяПлатформа
Функция ЭтоУчебнаяПлатформа() Экспорт
	
	Возврат ПараметрКлиента("ЭтоУчебнаяПлатформа");
	
КонецФункции

#Область ОбработкаСобытийПриложения

// Отключает выдачу предупреждения пользователю при завершении работы программы.
//
Процедура ПропуститьПредупреждениеПередЗавершениемРаботыСистемы() Экспорт
	
	ПараметрыПриложения.Вставить("СтандартныеПодсистемы.ПропуститьПредупреждениеПередЗавершениемРаботыСистемы", Истина);
	
КонецПроцедуры

// Выполнить стандартные действия перед началом работы пользователя
// с областью данных, либо в локальном режиме работы.
//
// Предназначена для вызова из обработчика ПередНачаломРаботыСистемы модулей управляемого и обычного приложения.
//
// Параметры:
//  ОповещениеЗавершения - ОписаниеОповещения - не задается при вызове из обработчика ПередНачаломРаботыСистемы 
//                         модулей управляемого и обычного приложения. В других случаях, после запуска будет вызвано
//                         оповещение с параметром типа Структура со свойствами:
//                         > Отказ - Булево - Ложь, если запуск выполнен успешно, или Истина, если вход в программу не
//                         выполнен;
//                         > Перезапустить - Булево - если требуется перезапуск программы;
//                         > ДополнительныеПараметрыКоманднойСтроки - Строка - для перезапуска.
//
Процедура ПередНачаломРаботыСистемы(Знач ОповещениеЗавершения = Неопределено) Экспорт
	
	ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	
	Если ПараметрыПриложения = Неопределено Тогда
		ПараметрыПриложения = Новый Соответствие;
	КонецЕсли;
	
	ПараметрыПриложения.Вставить("СтандартныеПодсистемы.ОценкаПроизводительности.ВремяНачалаЗапуска", ВремяНачала);
	
	Если ОповещениеЗавершения <> Неопределено Тогда
		ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("СтандартныеПодсистемыКлиент.ПередНачаломРаботыСистемы", 
			"ОповещениеЗавершения", ОповещениеЗавершения, Тип("ОписаниеОповещения"));
	КонецЕсли;
	
	ВойтиВОбластьДанных();
	
	ДействияПередНачаломРаботыСистемы(ОповещениеЗавершения);
	
	Если Не ОтключенаЛогикаНачалаРаботыСистемы()
	   И Не ОбщегоНазначенияКлиент.ПодсистемаСуществует("ИнтернетПоддержкаПользователей.БазоваяФункциональностьБИП") Тогда
		Возврат;
	КонецЕсли;
	
	Попытка
		МодульИнтернетПоддержкаПользователейКлиентСервер =
			ОбщегоНазначенияКлиент.ОбщийМодуль("ИнтернетПоддержкаПользователейКлиентСервер");
	Исключение
		Если ОтключенаЛогикаНачалаРаботыСистемы() Тогда
			Возврат;
		КонецЕсли;
		ВызватьИсключение;
	КонецПопытки;
	
	ВерсияБИП = МодульИнтернетПоддержкаПользователейКлиентСервер.ВерсияБиблиотеки();
	// Подключение обработчика запроса настроек клиента лицензирования
	// для корректной проверки легальности обновления.
	Если ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ВерсияБИП, "2.7.1.0") > 0 Тогда
		МодульКлиентЛицензированияКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("КлиентЛицензированияКлиент");
		МодульКлиентЛицензированияКлиент.ПодключитьЗапросНастроекКлиентаЛицензирования();
	КонецЕсли;
	
КонецПроцедуры

// Выполнить стандартные действия при начале работы пользователя
// с областью данных, либо в локальном режиме работы.
//
// Предназначена для вызова из обработчика ПриНачалеРаботыСистемы модулей управляемого и обычного приложения.
//
// Параметры:
//  ОповещениеЗавершения - ОписаниеОповещения - не задается при вызове из обработчика ПриНачалеРаботыСистемы 
//                         модулей управляемого и обычного приложения. В других случаях, после запуска будет вызвано
//                         оповещение с параметром типа Структура со свойствами:
//                         > Отказ - Булево - Ложь, если запуск выполнен успешно, или Истина, если вход в программу не
//                         выполнен;
//                         > Перезапустить - Булево - если требуется перезапуск программы;
//                         > ДополнительныеПараметрыКоманднойСтроки - Строка - для перезапуска.
//
//  НепрерывноеВыполнение - Булево - только для внутреннего использования.
//                          Для перехода из обработчика ПередНачаломРаботыСистемы
//                          выполненного в режиме интерактивной обработки.
//
Процедура ПриНачалеРаботыСистемы(Знач ОповещениеЗавершения = Неопределено, НепрерывноеВыполнение = Истина) Экспорт
	
	Если ВыполняетсяИнтерактивнаяОбработкаПередНачаломРаботыСистемы() Тогда
		Возврат;
	КонецЕсли;
	
	Если ОтключенаЛогикаНачалаРаботыСистемы() Тогда
		Возврат;
	КонецЕсли;
	
	Если ОповещениеЗавершения <> Неопределено Тогда
		ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("СтандартныеПодсистемыКлиент.ПриНачалеРаботыСистемы", 
			"ОповещениеЗавершения", ОповещениеЗавершения, Тип("ОписаниеОповещения"));
	КонецЕсли;
	ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("СтандартныеПодсистемыКлиент.ПриНачалеРаботыСистемы", 
		"НепрерывноеВыполнение", НепрерывноеВыполнение, Тип("Булево"));
	
	ДействияПриНачалеРаботыСистемы(ОповещениеЗавершения, НепрерывноеВыполнение);
	
КонецПроцедуры

// Выполнить стандартные действия перед завершением работы пользователя
// с областью данных, либо в локальном режиме работы.
//
// Предназначена для вызова из обработчика ПередЗавершениемРаботыСистемы модулей управляемого и обычного приложения.
//
// Параметры:
//  Отказ                - Булево - возвращаемое значение. Признак отказа от завершения работы 
//                         для обработчика события ПередЗавершениемРаботыСистемы, либо программного отказа,
//                         либо того, что потребовалась интерактивная обработка. В случае успешного взаимодействия
//                         с пользователем завершение работы будет продолжено.
//  ТекстПредупреждения  - Строка - см. ПередЗавершениемРаботыСистемы() в синтакс-помощнике.
//
Процедура ПередЗавершениемРаботыСистемы(Отказ = Ложь, ТекстПредупреждения = "") Экспорт
	
	Если Не ВыводитьПредупрежденияПередЗавершениемРаботыСистемы(Отказ) Тогда
		Возврат;
	КонецЕсли;
	
	Предупреждения = ПредупрежденияПередЗавершениемРаботыСистемы(Отказ);
	Если Предупреждения.Количество() = 0 Тогда
		Если Не ПараметрКлиента("ЗапрашиватьПодтверждениеПриЗавершенииПрограммы") Тогда
			Возврат;
		КонецЕсли;
		ТекстПредупреждения = НСтр("ru = 'Завершить работу с программой?'");
		Отказ = Истина;
	Иначе
		Отказ = Истина;
		МассивПредупреждений = Новый Массив;
		Для Каждого Предупреждение Из Предупреждения Цикл
			МассивПредупреждений.Добавить(Предупреждение.ТекстПредупреждения);
		КонецЦикла;
		Если Не ПустаяСтрока(ТекстПредупреждения) Тогда
			ТекстПредупреждения = ТекстПредупреждения + Символы.ПС;
		КонецЕсли;
		ТекстПредупреждения = ТекстПредупреждения + СтрСоединить(МассивПредупреждений, Символы.ПС);
		ПодключитьОбработчикОжидания("ПоказатьПредупрежденияПриЗавершенииРаботы", 0.1, Истина);
	КонецЕсли;
	УстановитьПараметрКлиента("ПредупрежденияПриЗавершенииРаботы", Предупреждения);
	
КонецПроцедуры

// Выполнить стандартные действия при обработке получения формы выбора пользователей системы взаимодействия.
//
// Параметры:
//  НазначениеВыбора - НазначениеВыбораПользователейСистемыВзаимодействия
//  Форма - ФормаКлиентскогоПриложения
//  ИдентификаторОбсуждения - ИдентификаторОбсужденияСистемыВзаимодействия
//  Параметры - Структура
//  ВыбраннаяФорма - Строка
//  СтандартнаяОбработка - Булево
//
Процедура ОбработкаПолученияФормыВыбораПользователейСистемыВзаимодействия(НазначениеВыбора,
			Форма, ИдентификаторОбсуждения, Параметры, ВыбраннаяФорма, СтандартнаяОбработка) Экспорт
	
	// СтандартныеПодсистемы.Обсуждения
	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.Обсуждения") Тогда
		МодульОбсужденияСлужебныйКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ОбсужденияСлужебныйКлиент");
		МодульОбсужденияСлужебныйКлиент.ПриПолученииФормыВыбораПользователейСистемыВзаимодействия(НазначениеВыбора,
			Форма, ИдентификаторОбсуждения, Параметры, ВыбраннаяФорма, СтандартнаяОбработка);
	КонецЕсли;
	// Конец СтандартныеПодсистемы.Обсуждения
		
КонецПроцедуры

// Возвращает новую структуру параметров для вывода предупреждения перед завершением работы программы.
// Для использования в ОбщегоНазначенияКлиентПереопределяемый.ПередЗавершениемРаботыСистемы.
//
// Возвращаемое значение:
//  Структура:
//    ТекстПредупреждения  - Строка - текст, выводимый в окне веб-браузера (или тонкого клиента) при завершении работы.
//                                    Например, "Имеются редактируемые файлы, которые не помещены в программу".
//                                    Остальные параметры определяют внешний вид формы предупреждений,
//                                    открываемой после подтверждения в окне веб-браузера (или тонкого клиента).
//    ТекстФлажка          - Строка - если задан, то в форме предупреждений выводится флажок с указанным текстом. 
//                                    Например, "Завершить редактирование файлов (5)".
//    ПоясняющийТекст      - Строка - текст, выводимый в форме сверху управляющего элемента (флажок или гиперссылка).
//                                    Например, "Редактируемые файлы, не помещенные в программу".
//    ТекстГиперссылки     - Строка - если задан, то выводится гиперссылка с указанным текстом.
//                                    Например, "Редактируемые файлы (5)".
//    РасширеннаяПодсказка - Строка - текст подсказки, выводимый по кнопке справа от управляющего элемента (флажок или
//                                    гиперссылка). Например, "Нажмите для перехода к списку файлов, 
//                                    открытых для редактирования".
//    Приоритет            - Число  - относительный порядок в списке предупреждений на форме (чем больше, тем выше).
//    ВывестиОдноПредупреждение - Булево - если Истина, то в списке предупреждений выводится только одно это
//                                         предупреждение. Т.е. такое предупреждение не совместимо с любыми другими.
//    ДействиеПриУстановленномФлажке - Структура:
//      * Форма          - Строка    - если пользователь установил флажок, то следует открыть указанную форму.
//                                     Например, "Обработка.Файлы.РедактируемыеФайлы".
//      * ПараметрыФормы - Структура - произвольная структура параметров для открытия формы. 
//    ДействиеПриНажатииГиперссылки - Структура:
//      * Форма          - Строка    - путь к форме, которая должна открываться по нажатию на гиперссылку.
//                                     Например, "Обработка.Файлы.РедактируемыеФайлы".
//      * ПараметрыФормы - Структура - произвольная структура параметров для открываемой формы.
//      * ПрикладнаяФормаПредупреждения - Строка - путь к форме, которая должна открываться сразу
//                                        вместо универсальной формы в случае, когда в списке 
//                                        предупреждений оказывается только одно данное предупреждение.
//                                        Например, "Обработка.Файлы.РедактируемыеФайлы".
//      * ПараметрыПрикладнойФормыПредупреждения - Структура - произвольная структура
//                                                 параметров для вышеописанной формы.
//      * РежимОткрытияОкна - РежимОткрытияОкнаФормы - режим открытия форм Форма или ПрикладнаяФормаПредупреждения.
// 
Функция ПредупреждениеПриЗавершенииРаботы() Экспорт
	
	ДействиеПриУстановленномФлажке = Новый Структура;
	ДействиеПриУстановленномФлажке.Вставить("Форма", "");
	ДействиеПриУстановленномФлажке.Вставить("ПараметрыФормы", Неопределено);
	
	ДействиеПриНажатииГиперссылки = Новый Структура;
	ДействиеПриНажатииГиперссылки.Вставить("Форма", "");
	ДействиеПриНажатииГиперссылки.Вставить("ПараметрыФормы", Неопределено);
	ДействиеПриНажатииГиперссылки.Вставить("ПрикладнаяФормаПредупреждения", "");
	ДействиеПриНажатииГиперссылки.Вставить("ПараметрыПрикладнойФормыПредупреждения", Неопределено);
	ДействиеПриНажатииГиперссылки.Вставить("РежимОткрытияОкна", Неопределено);
	
	ПараметрыПредупреждения = Новый Структура;
	ПараметрыПредупреждения.Вставить("ТекстФлажка", "");
	ПараметрыПредупреждения.Вставить("ПоясняющийТекст", "");
	ПараметрыПредупреждения.Вставить("ТекстПредупреждения", "");
	ПараметрыПредупреждения.Вставить("РасширеннаяПодсказка", "");
	ПараметрыПредупреждения.Вставить("ТекстГиперссылки", "");
	ПараметрыПредупреждения.Вставить("ДействиеПриУстановленномФлажке", ДействиеПриУстановленномФлажке);
	ПараметрыПредупреждения.Вставить("ДействиеПриНажатииГиперссылки", ДействиеПриНажатииГиперссылки);
	ПараметрыПредупреждения.Вставить("Приоритет", 0);
	ПараметрыПредупреждения.Вставить("ВывестиОдноПредупреждение", Ложь);
	
	Возврат ПараметрыПредупреждения;
	
КонецФункции

// Возвращает значения параметров, необходимых для работы клиентского кода
// при запуске конфигурации за один серверный вызов (для минимизации клиент-серверного взаимодействия
// и снижения времени запуска). 
// С помощью этой функции можно обращаться к параметрам в клиентском коде, вызываемым из обработчиков событий:
// - ПередНачаломРаботыСистемы,
// - ПриНачалеРаботыСистемы.
//
// В этих обработчиках при запуске недопустимо использовать команды сброса кэша
// повторно используемых модулей, иначе запуск может привести
// к непредсказуемым ошибкам и лишним серверным вызовам.
// 
// Возвращаемое значение:
//   ФиксированнаяСтруктура - параметры работы клиента при запуске. 
//                            См. в ОбщегоНазначенияПереопределяемый.ПриДобавленииПараметровРаботыКлиентаПриЗапуске.
//
//
Функция ПараметрыРаботыКлиентаПриЗапуске() Экспорт
	
	Возврат СтандартныеПодсистемыКлиентПовтИсп.ПараметрыРаботыКлиентаПриЗапуске();
	
КонецФункции

// Возвращает значения параметров, необходимых для работы клиентского кода конфигурации
// без дополнительных серверных вызовов.
// 
// Возвращаемое значение:
//   ФиксированнаяСтруктура - параметры работы клиента.
//                            Состав свойств см. в ОбщегоНазначенияПереопределяемый.ПриДобавленииПараметровРаботыКлиента.
//
Функция ПараметрыРаботыКлиента() Экспорт
	
	Возврат СтандартныеПодсистемыКлиентПовтИсп.ПараметрыРаботыКлиента();
	
КонецФункции

#КонецОбласти

#Область ДляВызоваИзДругихПодсистем

// Вызывается при получении оповещений от сервера.
// Оповещения отправляются на сервере в процедурах ПриОтправкеСерверногоОповещения.
// Список оповещений смотри в ОбщегоНазначенияПереопределяемый.ПриДобавленииСерверныхОповещений.
// 
// Параметры:
//  ИмяОповещения - см. СерверныеОповещения.ОтправитьСерверноеОповещение.ИмяОповещения
//  Результат     - см. СерверныеОповещения.ОтправитьСерверноеОповещение.Результат
//
// Пример:
//	Если ИмяОповещения <> "СтандартныеПодсистемы.ЗавершениеРаботыПользователей.БлокировкаСеансов" Тогда
//		Возврат;
//	КонецЕсли;
//	Если РаботаПользователейЗавершается() Тогда
//		ЗавершитьРаботуПользователей(Результат);
//	ИначеЕсли ВключенКонтрольЗавершенияРаботыПользователей() Тогда
//		КонтрольРежимаЗавершенияРаботыПользователей(Результат);
//	КонецЕсли;
//
Процедура ПриПолученииСерверногоОповещения(ИмяОповещения, Результат) Экспорт
	
	Если ИмяОповещения = "СтандартныеПодсистемы.БазоваяФункциональность.ФункциональныеОпцииИзменены" Тогда
		ОтключитьОбработчикОжидания("ОбновитьИнтерфейсПриИзмененииФункциональныхОпций");
		ПодключитьОбработчикОжидания("ОбновитьИнтерфейсПриИзмененииФункциональныхОпций", 5*60, Истина);
		
	ИначеЕсли ИмяОповещения = "СтандартныеПодсистемы.БазоваяФункциональность.ПовторноИспользуемыеЗначенияУстарели" Тогда
		ОбновитьПовторноИспользуемыеЗначения();
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#КонецОбласти

#Область СлужебныйПрограммныйИнтерфейс

Функция ЗапускПрограммыЗавершен() Экспорт
	
	ИмяПараметра = "СтандартныеПодсистемы.ЗапускПрограммыЗавершен";
	Если ПараметрыПриложения[ИмяПараметра] = Истина Тогда
		Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

Функция ПараметрКлиента(ИмяПараметра = Неопределено) Экспорт
	
	ИмяГлобальногоПараметра = "СтандартныеПодсистемы.ПараметрыКлиента";
	ПараметрыКлиента = ПараметрыПриложения[ИмяГлобальногоПараметра];
	
	Если ПараметрыКлиента = Неопределено Тогда
		// Заполнение постоянных параметров клиента.
		СтандартныеПодсистемыКлиентПовтИсп.ПараметрыРаботыКлиентаПриЗапуске();
		ПараметрыКлиента = ПараметрыПриложения[ИмяГлобальногоПараметра];
	КонецЕсли;
	
	Если ИмяПараметра = Неопределено Тогда
		Возврат ПараметрыКлиента;
	Иначе
		Возврат ПараметрыКлиента[ИмяПараметра];
	КонецЕсли;
	
КонецФункции

Процедура УстановитьПараметрКлиента(ИмяПараметра, Значение) Экспорт
	ИмяГлобальногоПараметра = "СтандартныеПодсистемы.ПараметрыКлиента";
	ПараметрыПриложения[ИмяГлобальногоПараметра].Вставить(ИмяПараметра, Значение);
КонецПроцедуры

Процедура ЗаполнитьПараметрыКлиента(ПараметрыКлиента) Экспорт
	
	ИмяПараметра = "СтандартныеПодсистемы.ПараметрыКлиента";
	Если ТипЗнч(ПараметрыПриложения[ИмяПараметра]) <> Тип("Структура") Тогда
		ПараметрыПриложения[ИмяПараметра] = Новый Структура;
		ПараметрыПриложения[ИмяПараметра].Вставить("РазделениеВключено");
		ПараметрыПриложения[ИмяПараметра].Вставить("ИнформационнаяБазаФайловая");
		ПараметрыПриложения[ИмяПараметра].Вставить("ЭтоБазоваяВерсияКонфигурации");
		ПараметрыПриложения[ИмяПараметра].Вставить("ЭтоУчебнаяПлатформа");
		ПараметрыПриложения[ИмяПараметра].Вставить("ЭтоСеансВнешнегоПользователя");
		ПараметрыПриложения[ИмяПараметра].Вставить("ЭтоПолноправныйПользователь");
		ПараметрыПриложения[ИмяПараметра].Вставить("ЭтоАдминистраторСистемы");
		ПараметрыПриложения[ИмяПараметра].Вставить("АвторизованныйПользователь");
		ПараметрыПриложения[ИмяПараметра].Вставить("ЗапрашиватьПодтверждениеПриЗавершенииПрограммы");
		ПараметрыПриложения[ИмяПараметра].Вставить("ДоступноИспользованиеРазделенныхДанных");
		ПараметрыПриложения[ИмяПараметра].Вставить("ПараметрыАвтономнойРаботы");
		ПараметрыПриложения[ИмяПараметра].Вставить("ПерсональныеНастройкиРаботыСФайлами");
		ПараметрыПриложения[ИмяПараметра].Вставить("КоличествоЗанятыхФайлов");
		ПараметрыПриложения[ИмяПараметра].Вставить("РезервноеКопированиеИБПриЗавершенииРаботы");
		ПараметрыПриложения[ИмяПараметра].Вставить("ОтображатьПомощникНастройкиРазрешений");
		ПараметрыПриложения[ИмяПараметра].Вставить("ПоправкаКВремениСеанса");
		ПараметрыПриложения[ИмяПараметра].Вставить("ПоправкаКУниверсальномуВремени");
		ПараметрыПриложения[ИмяПараметра].Вставить("СмещениеСтандартногоВремени");
		ПараметрыПриложения[ИмяПараметра].Вставить("СмещениеДатыКлиента");
		ПараметрыПриложения[ИмяПараметра].Вставить("КодОсновногоЯзыка");
	КонецЕсли;
	Если Не ПараметрыПриложения[ИмяПараметра].Свойство("ОценкаПроизводительности")
	   И ПараметрыКлиента.Свойство("ОценкаПроизводительности") Тогда
		ПараметрыПриложения[ИмяПараметра].Вставить("ОценкаПроизводительности");
	КонецЕсли;
	
	ЗаполнитьЗначенияСвойств(ПараметрыПриложения[ИмяПараметра], ПараметрыКлиента);
	
КонецПроцедуры

// После предупреждения вызывает процедуру с параметрами Результат, ДополнительныеПараметры.
//
// Параметры:
//  Параметры           - Структура - которая содержит свойство:
//                          ОбработкаПродолжения - ОписаниеОповещения - которое
//                          содержит процедуру с двумя параметрами:
//                            Результат, ДополнительныеПараметры.
//
//  ОписаниеПредупреждения - Неопределено - предупреждение не требуется.
//  ОписаниеПредупреждения - Строка - текст предупреждения, который нужно показать.
//  ОписаниеПредупреждения - Структура:
//       * ТекстПредупреждения - Строка - текст предупреждения, который нужно показать.
//       * Кнопки              - СписокЗначений - для процедуры ПоказатьВопросПользователю.
//       * ПараметрыВопроса    - Структура - содержит подмножество свойств,
//                                 которые нужно переопределить, из числа
//                                 возвращаемых функцией ПараметрыВопросаПользователю.
//
Процедура ПоказатьПредупреждениеИПродолжить(Параметры, ОписаниеПредупреждения) Экспорт
	
	ОповещениеСРезультатом = Параметры.ОбработкаПродолжения;
	
	Если ОписаниеПредупреждения = Неопределено Тогда
		ВыполнитьОбработкуОповещения(ОповещениеСРезультатом);
		Возврат;
	КонецЕсли;
	
	Кнопки = Новый СписокЗначений;
	ПараметрыВопроса = ПараметрыВопросаПользователю();
	ПараметрыВопроса.ПредлагатьБольшеНеЗадаватьЭтотВопрос = Ложь;
	ПараметрыВопроса.БлокироватьВесьИнтерфейс = Истина;
	ПараметрыВопроса.Картинка = БиблиотекаКартинок.Предупреждение32;
	
	Если Параметры.Отказ Тогда
		Кнопки.Добавить("Завершить", НСтр("ru = 'Завершить работу'"));
		ПараметрыВопроса.КнопкаПоУмолчанию = "Завершить";
	Иначе
		Кнопки.Добавить("Продолжить", НСтр("ru = 'Продолжить'"));
		Кнопки.Добавить("Завершить",  НСтр("ru = 'Завершить работу'"));
		ПараметрыВопроса.КнопкаПоУмолчанию = "Продолжить";
	КонецЕсли;
	
	Если ТипЗнч(ОписаниеПредупреждения) = Тип("Структура") Тогда
		ТекстПредупреждения = ОписаниеПредупреждения.ТекстПредупреждения;
		Кнопки = ОписаниеПредупреждения.Кнопки;
		ЗаполнитьЗначенияСвойств(ПараметрыВопроса, ОписаниеПредупреждения.ПараметрыВопроса);
	Иначе
		ТекстПредупреждения = ОписаниеПредупреждения;
	КонецЕсли;
	
	ОповещениеОЗакрытии = Новый ОписаниеОповещения("ПоказатьПредупреждениеИПродолжитьЗавершение", ЭтотОбъект, Параметры);
	ПоказатьВопросПользователю(ОповещениеОЗакрытии, ТекстПредупреждения, Кнопки, ПараметрыВопроса);
	
КонецПроцедуры

// Возвращает имя исполняемого файла в зависимости от вида клиента.
//
// Возвращаемое значение:
//  Строка
//
Функция ИмяИсполняемогоФайлаПриложения(ПолучитьИмяФайлаКонфигуратора = Ложь) Экспорт
	
	ШаблонИмениФайла = "1cv8[УчебнаяПлатформа].exe";
	
#Если ТонкийКлиент Тогда
	Если Не ПолучитьИмяФайлаКонфигуратора Тогда
		ШаблонИмениФайла = "1cv8c[УчебнаяПлатформа].exe";
	КонецЕсли;	
#КонецЕсли
	
	Возврат СтрЗаменить(ШаблонИмениФайла, "[УчебнаяПлатформа]", ?(ЭтоУчебнаяПлатформа(), "t", ""));
	
КонецФункции

// Устанавливает / отменяет хранение ссылки на управляемую форму в глобальной переменной.
// Требуется для случаев, когда ссылка на форму передается через ДополнительныеПараметры
// в объекте ОписаниеОповещения, который не блокирует освобождение закрытой формы.
//
Процедура УстановитьХранениеФормы(Форма, Хранение) Экспорт
	
	Хранилище = ПараметрыПриложения["СтандартныеПодсистемы.ВременноеХранилищеСсылокНаУправляемыеФормы"];
	Если Хранилище = Неопределено Тогда
		Хранилище = Новый Соответствие;
		ПараметрыПриложения.Вставить("СтандартныеПодсистемы.ВременноеХранилищеСсылокНаУправляемыеФормы", Хранилище);
	КонецЕсли;
	
	Если Хранение Тогда
		Хранилище.Вставить(Форма, Новый Структура("Форма", Форма));
	ИначеЕсли Хранилище.Получить(Форма) <> Неопределено Тогда
		Хранилище.Удалить(Форма);
	КонецЕсли;
	
КонецПроцедуры

// Проверяет, что текущие данные определены и не являются группировкой.
// Предназначена для обработчиков таблиц формы динамических списков.
//
// Параметры:
//  ТаблицаИлиТекущиеДанные - ТаблицаФормы - таблица формы динамического списка для проверки текущих данных.
//                          - Неопределено
//                          - ДанныеФормыСтруктура
//                          - Структура - текущие данные для проверки.
//
// Возвращаемое значение:
//  Булево
//
Функция ЭтоЭлементДинамическогоСписка(ТаблицаИлиТекущиеДанные) Экспорт
	
	Если ТипЗнч(ТаблицаИлиТекущиеДанные) = Тип("ТаблицаФормы") Тогда
		ТекущиеДанные = ТаблицаИлиТекущиеДанные.ТекущиеДанные;
	Иначе
		ТекущиеДанные = ТаблицаИлиТекущиеДанные;
	КонецЕсли;
	
	Если ТипЗнч(ТекущиеДанные) <> Тип("ДанныеФормыСтруктура")
	   И ТипЗнч(ТекущиеДанные) <> Тип("Структура") Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если ТекущиеДанные.Свойство("ГруппировкаСтроки") Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

// Проверяет, выполнено ли опасное отключение процедур запуска для целей автоматического тестирования.
//
// Возвращаемое значение:
//  Булево
//
Функция ОтключенаЛогикаНачалаРаботыСистемы() Экспорт
	Возврат СтрНайти(ПараметрЗапуска, "ОтключитьЛогикуНачалаРаботыСистемы") > 0;
КонецФункции

// Возвращает элементы стиля конфигурации.
//
// Возвращаемое значение:
//  Структура:
//   * Ключ - Строка - имя элемента стиля, например, "ГиперссылкаЦвет".
//   * Значение - ОбъектМетаданныхЭлементСтиля.
//
Функция ЭлементыСтиля() Экспорт
	
	ЭлементыСтиля = Новый Структура;
	
	ПараметрыРаботыКлиента = ПараметрыРаботыКлиента();
	Для каждого ЭлементСтиля Из ПараметрыРаботыКлиента.ЭлементыСтиля Цикл
#Если ТолстыйКлиентОбычноеПриложение Тогда
		ЭлементыСтиля.Вставить(ЭлементСтиля.Ключ, ЭлементСтиля.Значение.Получить());
#Иначе
		ЭлементыСтиля.Вставить(ЭлементСтиля.Ключ, ЭлементСтиля.Значение);
#КонецЕсли
	КонецЦикла;
	
	Возврат ЭлементыСтиля;
	
КонецФункции

// Переадресует оповещение без результата на оповещение с результатом.
//
// Возвращаемое значение:
//  ОписаниеОповещения
//
Функция ОповещениеБезРезультата(ОповещениеСРезультатом) Экспорт
	
	Возврат Новый ОписаниеОповещения("ВыполнитьОповещениеСПустымРезультатом", ЭтотОбъект, ОповещениеСРезультатом);
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Обработчики событий подсистем конфигурации.

// См. ИнтеграцияПодсистемБСПКлиент.ПередПериодическойОтправкойДанныхКлиентаНаСервер
Процедура ПередПериодическойОтправкойДанныхКлиентаНаСервер(Параметры) Экспорт
	
	ИмяПараметра = "СтандартныеПодсистемы.БазоваяФункциональность.КонтрольДинамическогоОбновления";
	Если Не СерверныеОповещенияКлиент.ЗакончилосьВремяОжидания(ИмяПараметра) Тогда
		Возврат;
	КонецЕсли;
	
	// ИзмененаКонфигурацияИлиРасширения
	Параметры.Вставить(ИмяПараметра, Истина);
	
КонецПроцедуры

// См. ОбщегоНазначенияКлиентПереопределяемый.ПослеПериодическогоПолученияДанныхКлиентаНаСервере
Процедура ПослеПериодическогоПолученияДанныхКлиентаНаСервере(Результаты) Экспорт
	
	ИмяПараметра = "СтандартныеПодсистемы.БазоваяФункциональность.КонтрольДинамическогоОбновления";
	Результат = Результаты.Получить(ИмяПараметра);
	Если Результат = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	// ИзмененаКонфигурацияИлиРасширения
	КартинкаДиалогИнформация = БиблиотекаКартинок.ДиалогИнформация;
	ПоказатьОповещениеПользователя(
		НСтр("ru = 'Установлено обновление приложения'"),
		"e1cib/app/ОбщаяФорма.КонтрольДинамическогоОбновления",
		Результат, КартинкаДиалогИнформация,
		СтатусОповещенияПользователя.Важное,
		"УстановленоОбновлениеПрограммы");
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Вывод результата выполнения.

// Разворачивает узлы указанного дерева на форме.
//
// Параметры:
//   Форма                     - ФормаКлиентскогоПриложения - форма, на которой размещен элемент управления с деревом значений.
//   ИмяЭлементаФормы          - Строка           - имя элемента с таблицей формы (деревом значений) и связанного с ней
//                                                  реквизита формы (должны совпадать).
//   ИдентификаторСтрокиДерева - Произвольный     - идентификатор строки дерева, которую требуется развернуть.
//                                                  Если указано "*", то будут развернуты все узлы верхнего уровня.
//                                                  Если указано Неопределено, то строки дерева развернуты не будут.
//                                                  Значение по умолчанию: "*".
//   РазвернутьСПодчиненными   - Булево           - если Истина, то следует раскрыть также и все подчиненные узлы.
//                                                  По умолчанию Ложь.
//
Процедура РазвернутьУзлыДерева(Форма, ИмяЭлементаФормы, ИдентификаторСтрокиДерева = "*", РазвернутьСПодчиненными = Ложь) Экспорт
	
	ТаблицаЭлемент = Форма.Элементы[ИмяЭлементаФормы];
	Если ИдентификаторСтрокиДерева = "*" Тогда
		Узлы = Форма[ИмяЭлементаФормы].ПолучитьЭлементы();
		Для Каждого Узел Из Узлы Цикл
			ТаблицаЭлемент.Развернуть(Узел.ПолучитьИдентификатор(), РазвернутьСПодчиненными);
		КонецЦикла;
	Иначе
		ТаблицаЭлемент.Развернуть(ИдентификаторСтрокиДерева, РазвернутьСПодчиненными);
	КонецЕсли;
	
КонецПроцедуры

// Оповещает открытые форм и динамические списки о массовых изменениях объектов различных типов
// с помощью методов глобального контекста Оповестить и ОповеститьОбИзменении.
//
// Параметры:
//  ТипыИзмененныхОбъектов - см. СтандартныеПодсистемыСервер.ПодготовитьОповещениеФормОбИзменении
//  ПараметрОповещенияФорм - Произвольный - параметр сообщения для метода Оповестить.
//
Процедура ОповеститьФормыОбИзменении(ТипыИзмененныхОбъектов, ПараметрОповещенияФорм = Неопределено) Экспорт
	
	Для Каждого ТипОбъекта Из ТипыИзмененныхОбъектов Цикл
		Оповестить(ТипОбъекта.Значение.ИмяСобытия, 
			?(ПараметрОповещенияФорм <> Неопределено, ПараметрОповещенияФорм, Новый Структура), 
			ТипОбъекта.Значение.ПустаяСсылка);
		ОповеститьОбИзменении(ТипОбъекта.Ключ);
	КонецЦикла;
	
КонецПроцедуры

// Открывает форму списка объекта с позиционированием на объекте.
//
// Параметры:
//   Ссылка - ЛюбаяСсылка - объект, который необходимо показать в списке.
//   ИмяФормыСписка - Строка - имя формы списка.
//       Если передать Неопределено то будет определена автоматически (потребуется вызов сервера).
//   ПараметрыФормы - Структура - дополнительные параметры открытия формы списка.
//
Процедура ПоказатьВСписке(Ссылка, ИмяФормыСписка, ПараметрыФормы = Неопределено) Экспорт
	Если Ссылка = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ИмяФормыСписка = Неопределено Тогда
		ПолноеИмя = СтандартныеПодсистемыВызовСервера.ПолноеИмяОбъектаМетаданных(ТипЗнч(Ссылка));
		Если ПолноеИмя = Неопределено Тогда
			Возврат;
		КонецЕсли;
		ИмяФормыСписка = ПолноеИмя + ".ФормаСписка";
	КонецЕсли;
	
	Если ПараметрыФормы = Неопределено Тогда
		ПараметрыФормы = Новый Структура;
	КонецЕсли;
	
	ПараметрыФормы.Вставить("ТекущаяСтрока", Ссылка);
	
	Форма = ПолучитьФорму(ИмяФормыСписка, ПараметрыФормы, , Истина);
	Форма.Открыть();
	Форма.ВыполнитьПереход(Ссылка);
КонецПроцедуры

// Выводит текст, который пользователь может скопировать.
//
// Параметры:
//   Обработчик - ОписаниеОповещения - описание процедуры, которая будет вызвана после завершения показа.
//       Возвращаемое значение аналогично ПоказатьВопросПользователю().
//   Текст     - Строка - текст информации.
//   Заголовок - Строка - заголовок окна. По умолчанию "Подробнее".
//
Процедура ПоказатьПодробнуюИнформацию(Обработчик, Текст, Заголовок = Неопределено) Экспорт
	НастройкиДиалога = Новый Структура;
	НастройкиДиалога.Вставить("ПредлагатьБольшеНеЗадаватьЭтотВопрос", Ложь);
	НастройкиДиалога.Вставить("Картинка", Неопределено);
	НастройкиДиалога.Вставить("ПоказыватьКартинку", Ложь);
	НастройкиДиалога.Вставить("МожноКопировать", Истина);
	НастройкиДиалога.Вставить("КнопкаПоУмолчанию", 0);
	НастройкиДиалога.Вставить("ВыделятьКнопкуПоУмолчанию", Ложь);
	НастройкиДиалога.Вставить("Заголовок", Заголовок);
	
	Если Не ЗначениеЗаполнено(НастройкиДиалога.Заголовок) Тогда
		НастройкиДиалога.Заголовок = НСтр("ru = 'Подробнее'");
	КонецЕсли;
	
	Кнопки = Новый СписокЗначений;
	Кнопки.Добавить(0, НСтр("ru = 'Закрыть'"));
	
	ПоказатьВопросПользователю(Обработчик, Текст, Кнопки, НастройкиДиалога);
КонецПроцедуры

// Шапка файла для технической поддержки.
//
// Возвращаемое значение:
//  Строка
//
Функция ИнформацияДляПоддержки() Экспорт
	
	Текст = НСтр("ru = 'Название программы: [НазваниеПрограммы] 
	                   |Версия программы: [ВерсияПрограммы]; 
	                   |Версия Платформы 1С:Предприятие: [ВерсияПлатформы] [РазрядностьПлатформы]; 
	                   |Версия Библиотеки стандартных подсистем: [ВерсияБСП];
	                   |Операционная система: [ОперационнаяСистема];
	                   |Размер оперативной памяти: [ОперативнаяПамять];
	                   |Имя COM соединителя: [ИмяCOMСоединителя];
	                   |Базовая: [ЭтоБазоваяВерсияКонфигурации]
	                   |Полноправный пользователь: [ЭтоПолноправныйПользователь]
	                   |Учебная: [ЭтоУчебнаяПлатформа]
	                   |Конфигурация изменена: [КонфигурацияИзменена]'") + Символы.ПС;
	
	Параметры = ?(ЗапускПрограммыЗавершен(), ПараметрыРаботыКлиента(), ПараметрыРаботыКлиентаПриЗапуске());
	СистемнаяИнформация = Новый СистемнаяИнформация;
	ТекстНедоступно = НСтр("ru = 'недоступно'");
	
	Текст = СтрЗаменить(Текст, "[НазваниеПрограммы]", 
		?(Параметры.Свойство("ПодробнаяИнформация"), Параметры.ПодробнаяИнформация, ТекстНедоступно));
	Текст = СтрЗаменить(Текст, "[ВерсияПрограммы]", 
		?(Параметры.Свойство("ВерсияКонфигурации"), Параметры.ВерсияКонфигурации, ТекстНедоступно));
	Текст = СтрЗаменить(Текст, "[ВерсияПлатформы]", СистемнаяИнформация.ВерсияПриложения);
	Текст = СтрЗаменить(Текст, "[РазрядностьПлатформы]", СистемнаяИнформация.ТипПлатформы);
	Текст = СтрЗаменить(Текст, "[ВерсияБСП]", СтандартныеПодсистемыВызовСервера.ВерсияБиблиотеки());
	Текст = СтрЗаменить(Текст, "[ОперационнаяСистема]", СистемнаяИнформация.ВерсияОС);
	Текст = СтрЗаменить(Текст, "[ОперативнаяПамять]", СистемнаяИнформация.ОперативнаяПамять);
	Текст = СтрЗаменить(Текст, "[ИмяCOMСоединителя]", ОбщегоНазначенияКлиентСервер.ИмяCOMСоединителя());
	Текст = СтрЗаменить(Текст, "[ЭтоБазоваяВерсияКонфигурации]", ЭтоБазоваяВерсияКонфигурации());
	Текст = СтрЗаменить(Текст, "[ЭтоПолноправныйПользователь]", ПользователиКлиент.ЭтоПолноправныйПользователь());
	Текст = СтрЗаменить(Текст, "[ЭтоУчебнаяПлатформа]", ЭтоУчебнаяПлатформа());
	Текст = СтрЗаменить(Текст, "[КонфигурацияИзменена]", 
		?(Параметры.Свойство("НастройкиОбновления"), Параметры.НастройкиОбновления.КонфигурацияИзменена, ТекстНедоступно));
	
	Возврат Текст;
	
КонецФункции

#Если Не ВебКлиент И Не МобильныйКлиент Тогда

// Каталог системных приложений, например, "C:\Windows\System32".
// Используется только в ОС Windows.
//
// Возвращаемое значение:
//  Строка
//
Функция КаталогСистемныхПриложений() Экспорт
	
	ОбъектShell = Новый COMОбъект("Shell.Application");
	
	СистемнаяИнформация = Новый СистемнаяИнформация;
	Если СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86 Тогда 
		// Для 32-битной системы "C:\Windows\System32".
		// Для 64-битной системы "C:\Windows\SysWOW64".
		ОбъектFolder = ОбъектShell.Namespace(41);
	ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64 Тогда 
		// Для любой системы "C:\Windows\System32".
		ОбъектFolder = ОбъектShell.Namespace(37);
	КонецЕсли;
	
	Возврат ОбъектFolder.Self.Path + "\";
	
КонецФункции

#КонецЕсли

// Асинхронный аналог метода платформы ВыполнитьОбработкуОповещения.
// Выполняет обработку оповещения асинхронно, подобно методам платформы, например НачатьПолучениеФайла.
// Используется, когда обработку оповещения нужно выполнить после синхронного завершения вызова,
// то есть с некоторой минимальной задержкой.
// 
// Параметры:
//  Оповещение - ОписаниеОповещения - оповещение, которое нужно выполнить.
//  Результат  - Произвольный - значение, которое передается в параметр Результат
//               метода платформы ВыполнитьОбработкуОповещения.
//
Процедура НачатьВыполнениеОбработкиОповещения(Оповещение, Результат = Неопределено) Экспорт
	
	Контекст = Новый Структура;
	Контекст.Вставить("Оповещение", Оповещение);
	Контекст.Вставить("Результат", Результат);
	
	Поток = Новый ПотокВПамяти;
	Поток.НачатьПолучениеРазмера(Новый ОписаниеОповещения(
		"НачатьВыполнениеОбработкиОповещенияЗавершение", ЭтотОбъект, Контекст));
	
КонецПроцедуры

// Параметры:
//  ИнформацияОбОшибке - ИнформацияОбОшибке
//
Процедура ПоказатьИнформациюОбОшибкеИПродолжить(ИнформацияОбОшибке) Экспорт
	
	ОбработкаОшибок.ПоказатьИнформациюОбОшибке(ИнформацияОбОшибке);
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

////////////////////////////////////////////////////////////////////////////////
// ПередНачаломРаботыСистемы

// Продолжение процедуры ПередНачаломРаботыСистемы.
Процедура ДействияПередНачаломРаботыСистемы(ОповещениеЗавершения)
	
	Параметры = ПараметрыОбработкиПередНачаломРаботыСистемы();
	
	// Внешние параметры описания результата.
	Параметры.Вставить("Отказ", Ложь);
	Параметры.Вставить("Перезапустить", Ложь);
	Параметры.Вставить("ДополнительныеПараметрыКоманднойСтроки", "");
	
	// Внешние параметры управления выполнением.
	Параметры.Вставить("ИнтерактивнаяОбработка", Неопределено); // ОписаниеОповещения.
	Параметры.Вставить("ОбработкаПродолжения",   Неопределено); // ОписаниеОповещения.
	Параметры.Вставить("НепрерывноеВыполнение", Истина);
	Параметры.Вставить("ПолученныеПараметрыКлиента", Новый Структура);
	Параметры.Вставить("МодульПоследнейПроцедуры", "");
	Параметры.Вставить("ИмяПоследнейПроцедуры", "");
	УстановитьПоследнююПроцедуру(Параметры, "СтандартныеПодсистемыКлиент", "ПередНачаломРаботыСистемы");
	
	// Внутренние параметры.
	Параметры.Вставить("ОповещениеЗавершения", ОповещениеЗавершения);
	Параметры.Вставить("ОбработкаЗавершения", Новый ОписаниеОповещения(
		"ДействияПередНачаломРаботыСистемыОбработкаЗавершения", ЭтотОбъект));
	
	ОбновитьПараметрыРаботыКлиента(Параметры, Истина, ОповещениеЗавершения <> Неопределено);
	
	// Подготовка перехода к следующей процедуре.
	Параметры.Вставить("ОбработкаПродолжения", Новый ОписаниеОповещения(
		"ДействияПередНачаломРаботыСистемыВИнтеграционнойПроцедуре", ЭтотОбъект));
	
	Если ОтключенаЛогикаНачалаРаботыСистемы() Тогда
		Попытка
			// Проверка права отключения и заполнение параметров работы клиента на сервере.
			СвойстваКлиента = Новый Структура;
			ЗаполнитьПараметрыРаботыКлиентаНаСервере(СвойстваКлиента);
			СтандартныеПодсистемыВызовСервера.ПроверитьПравоОтключитьЛогикуНачалаРаботыСистемы(СвойстваКлиента);
			Если СвойстваКлиента.Свойство("ОшибкаНетПраваОтключитьЛогикуНачалаРаботыСистемы") Тогда
				ПользователиСлужебныйКлиент.УстановитьИнтерактивнуюОбработкуПриОшибкеНедостаточноПравДляВходаВПрограмму(
					Параметры, СвойстваКлиента.ОшибкаНетПраваОтключитьЛогикуНачалаРаботыСистемы);
			КонецЕсли;
		Исключение
			ТекстОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
			СтандартныеПодсистемыВызовСервера.ЗаписатьОшибкуВЖурналРегистрацииПриЗапускеИлиЗавершении(
				Ложь, "Запуск", ТекстОшибки);
			ПользователиСлужебныйКлиент.УстановитьИнтерактивнуюОбработкуПриОшибкеНедостаточноПравДляВходаВПрограмму(
				Параметры, ТекстОшибки);
		КонецПопытки;
		Если ИнтерактивнаяОбработкаПередНачаломРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		СкрытьРабочийСтолПриНачалеРаботыСистемы(Истина, Истина);
		Возврат;
	КонецЕсли;
	
	// Стандартный первый серверный вызов с целью предварительного
	// заполнения параметров работы клиента на сервере.
	Попытка
		ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.БазоваяФункциональность");
	Исключение
		ОбработатьОшибкуПередНачаломРаботыСистемы(Параметры, ИнформацияОбОшибке(), Истина);
	КонецПопытки;
	Если ИнтерактивнаяОбработкаПередНачаломРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы.
Процедура ДействияПередНачаломРаботыСистемыВИнтеграционнойПроцедуре(Неопределен, Контекст) Экспорт
	
	Параметры = ПараметрыОбработкиПередНачаломРаботыСистемы();
	УстановитьПоследнююПроцедуру(Параметры, "СтандартныеПодсистемыКлиент",
		"ДействияПередНачаломРаботыСистемыВИнтеграционнойПроцедуре");
	
	Если Не ПродолжитьДействияПередНачаломРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.Вставить("ОбработкаПродолжения", Новый ОписаниеОповещения(
		"ДействияПередНачаломРаботыСистемыВМодуляхИнтеграционнойПроцедуры", ЭтотОбъект));
	
	Параметры.Вставить("ИндексТекущегоМодуля", 0);
	Параметры.Вставить("ДобавленныеМодули", Новый Массив);
	Попытка
		Параметры.Вставить("Модули", Новый Массив);
		ИнтеграцияПодсистемБСПКлиент.ПередНачаломРаботыСистемы(Параметры);
		Параметры.Вставить("ДобавленныеМодули", Параметры.Модули);
		Параметры.Удалить("Модули");
	Исключение
		ОбработатьОшибкуПередНачаломРаботыСистемы(Параметры, ИнформацияОбОшибке(), Истина);
	КонецПопытки;
	Если ИнтерактивнаяОбработкаПередНачаломРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы.
Процедура ДействияПередНачаломРаботыСистемыВМодуляхИнтеграционнойПроцедуры(Неопределен, Контекст) Экспорт
	
	Пока Истина Цикл
		
		Параметры = ПараметрыОбработкиПередНачаломРаботыСистемы();
		УстановитьПоследнююПроцедуру(Параметры, "СтандартныеПодсистемыКлиент",
			"ДействияПередНачаломРаботыСистемыВМодуляхИнтеграционнойПроцедуры");
		
		Если Не ПродолжитьДействияПередНачаломРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		
		Если Параметры.ИндексТекущегоМодуля >= Параметры.ДобавленныеМодули.Количество() Тогда
			ДействияПередНачаломРаботыСистемыВПереопределяемойПроцедуре(Неопределено, Неопределено);
			Возврат;
		КонецЕсли;
	
		ОписаниеМодуля = Параметры.ДобавленныеМодули[Параметры.ИндексТекущегоМодуля];
		Параметры.ИндексТекущегоМодуля = Параметры.ИндексТекущегоМодуля + 1;
		
		Попытка
			Если ТипЗнч(ОписаниеМодуля) <> Тип("Структура") Тогда
				ТекущийМодуль = ОписаниеМодуля;
				ТекущийМодуль.ПередНачаломРаботыСистемы(Параметры);
			Иначе
				ТекущийМодуль = ОписаниеМодуля.Модуль;
				Если ОписаниеМодуля.Номер = 2 Тогда
					ТекущийМодуль.ПередНачаломРаботыСистемы2(Параметры);
				ИначеЕсли ОписаниеМодуля.Номер = 3 Тогда
					ТекущийМодуль.ПередНачаломРаботыСистемы3(Параметры);
				ИначеЕсли ОписаниеМодуля.Номер = 4 Тогда
					ТекущийМодуль.ПередНачаломРаботыСистемы4(Параметры);
				ИначеЕсли ОписаниеМодуля.Номер = 5 Тогда
					ТекущийМодуль.ПередНачаломРаботыСистемы5(Параметры);
				КонецЕсли;
			КонецЕсли;
		Исключение
			ОбработатьОшибкуПередНачаломРаботыСистемы(Параметры, ИнформацияОбОшибке(), Истина);
		КонецПопытки;
		Если ИнтерактивнаяОбработкаПередНачаломРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы.
Процедура ДействияПередНачаломРаботыСистемыВПереопределяемойПроцедуре(Неопределен, Контекст)
	
	Параметры = ПараметрыОбработкиПередНачаломРаботыСистемы();
	УстановитьПоследнююПроцедуру(Параметры, "СтандартныеПодсистемыКлиент",
		"ДействияПередНачаломРаботыСистемыВПереопределяемойПроцедуре");
	
	Если Не ПродолжитьДействияПередНачаломРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.Вставить("ОбработкаПродолжения", Новый ОписаниеОповещения(
		"ДействияПередНачаломРаботыСистемыВМодуляхПереопределяемойПроцедуры", ЭтотОбъект));
	
	Параметры.ИнтерактивнаяОбработка = Неопределено;
	
	Параметры.Вставить("ИндексТекущегоМодуля", 0);
	Параметры.Вставить("ДобавленныеМодули", Новый Массив);
	
	Если ОбщегоНазначенияКлиент.ДоступноИспользованиеРазделенныхДанных() Тогда
		Попытка
			Параметры.Вставить("Модули", Новый Массив);
			ОбщегоНазначенияКлиентПереопределяемый.ПередНачаломРаботыСистемы(Параметры);
			Параметры.Вставить("ДобавленныеМодули", Параметры.Модули);
			Параметры.Удалить("Модули");
		Исключение
			ОбработатьОшибкуПередНачаломРаботыСистемы(Параметры, ИнформацияОбОшибке());
		КонецПопытки;
		Если ИнтерактивнаяОбработкаПередНачаломРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы.
Процедура ДействияПередНачаломРаботыСистемыВМодуляхПереопределяемойПроцедуры(Неопределен, Контекст) Экспорт
	
	Пока Истина Цикл
		
		Параметры = ПараметрыОбработкиПередНачаломРаботыСистемы();
		УстановитьПоследнююПроцедуру(Параметры, "СтандартныеПодсистемыКлиент",
			"ДействияПередНачаломРаботыСистемыВМодуляхПереопределяемойПроцедуры");
		
		Если Не ПродолжитьДействияПередНачаломРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		
		Если Параметры.ИндексТекущегоМодуля >= Параметры.ДобавленныеМодули.Количество() Тогда
			ДействияПередНачаломРаботыСистемыПослеВсехПроцедур(Неопределено, Неопределено);
			Возврат;
		КонецЕсли;
		
		ТекущийМодуль = Параметры.ДобавленныеМодули[Параметры.ИндексТекущегоМодуля];
		Параметры.ИндексТекущегоМодуля = Параметры.ИндексТекущегоМодуля + 1;
		
		Попытка
			ТекущийМодуль.ПередНачаломРаботыСистемы(Параметры);
		Исключение
			ОбработатьОшибкуПередНачаломРаботыСистемы(Параметры, ИнформацияОбОшибке());
		КонецПопытки;
		Если ИнтерактивнаяОбработкаПередНачаломРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы.
Процедура ДействияПередНачаломРаботыСистемыПослеВсехПроцедур(Неопределен, Контекст)
	
	Параметры = ПараметрыОбработкиПередНачаломРаботыСистемы();
	УстановитьПоследнююПроцедуру(Параметры, "СтандартныеПодсистемыКлиент",
		"ДействияПередНачаломРаботыСистемыПослеВсехПроцедур");
	
	Если Не ПродолжитьДействияПередНачаломРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.Вставить("ОбработкаПродолжения", Параметры.ОбработкаЗавершения);
	
	Попытка
		УстановитьПараметрыФункциональныхОпцийИнтерфейсаПриЗапуске();
	Исключение
		ОбработатьОшибкуПередНачаломРаботыСистемы(Параметры, ИнформацияОбОшибке(), Истина);
	КонецПопытки;
	Если ИнтерактивнаяОбработкаПередНачаломРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Завершение процедуры ПередНачаломРаботыСистемы.
Процедура ДействияПередНачаломРаботыСистемыОбработкаЗавершения(Неопределен, Контекст) Экспорт
	
	Параметры = ПараметрыОбработкиПередНачаломРаботыСистемы(Истина);
	
	Параметры.ОбработкаПродолжения = Неопределено;
	Параметры.ОбработкаЗавершения  = Неопределено;
	
	ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"];
	ПараметрыПриЗапускеПрограммы.Удалить("ПолученныеПараметрыКлиента");
	ПараметрыПриложения["СтандартныеПодсистемы.ЗапускПрограммыЗавершен"] = Истина;
	
	Если Параметры.ОповещениеЗавершения <> Неопределено Тогда
		Результат = Новый Структура;
		Результат.Вставить("Отказ", Параметры.Отказ);
		Результат.Вставить("Перезапустить", Параметры.Перезапустить);
		Результат.Вставить("ДополнительныеПараметрыКоманднойСтроки", Параметры.ДополнительныеПараметрыКоманднойСтроки);
		ВыполнитьОбработкуОповещения(Параметры.ОповещениеЗавершения, Результат);
		Возврат;
	КонецЕсли;
	
	Если Параметры.Отказ Тогда
		Если Параметры.Перезапустить <> Истина Тогда
			ПрекратитьРаботуСистемы();
		ИначеЕсли ЗначениеЗаполнено(Параметры.ДополнительныеПараметрыКоманднойСтроки) Тогда
			ПрекратитьРаботуСистемы(Параметры.Перезапустить, Параметры.ДополнительныеПараметрыКоманднойСтроки);
		Иначе
			ПрекратитьРаботуСистемы(Параметры.Перезапустить);
		КонецЕсли;
		
	ИначеЕсли Не Параметры.НепрерывноеВыполнение Тогда
		Если ПараметрыПриЗапускеПрограммы.Свойство("ПараметрыОбработки") Тогда
			ПараметрыПриЗапускеПрограммы.Удалить("ПараметрыОбработки");
		КонецЕсли;
		ПодключитьОбработчикОжидания("ОбработчикОжиданияПриНачалеРаботыСистемы", 0.1, Истина);
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования.
Функция ПараметрыОбработкиПередНачаломРаботыСистемы(Удалить = Ложь)
	
	ИмяПараметра = "СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы";
	Свойства = ПараметрыПриложения[ИмяПараметра];
	Если Свойства = Неопределено Тогда
		Свойства = Новый Структура;
		ПараметрыПриложения.Вставить(ИмяПараметра, Свойства);
	КонецЕсли;
	
	ИмяСвойства = "ПараметрыОбработкиПередНачаломРаботыСистемы";
	Если Свойства.Свойство(ИмяСвойства) Тогда
		Параметры = Свойства[ИмяСвойства];
	Иначе
		Параметры = Новый Структура;
		Свойства.Вставить(ИмяСвойства, Параметры);
	КонецЕсли;
	
	Если Удалить Тогда
		Свойства.Удалить(ИмяСвойства);
	КонецЕсли;
	
	Возврат Параметры;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// ПриНачалеРаботыСистемы

// Продолжение процедуры ПриНачалеРаботыСистемы.
Процедура ДействияПриНачалеРаботыСистемы(ОповещениеЗавершения, НепрерывноеВыполнение)
	
	Параметры = ПараметрыОбработкиПриНачалеРаботыСистемы();
	
	// Внешние параметры описания результата.
	Параметры.Вставить("Отказ", Ложь);
	Параметры.Вставить("Перезапустить", Ложь);
	Параметры.Вставить("ДополнительныеПараметрыКоманднойСтроки", "");
	
	// Внешние параметры управления выполнением.
	Параметры.Вставить("ИнтерактивнаяОбработка", Неопределено); // ОписаниеОповещения.
	Параметры.Вставить("ОбработкаПродолжения",   Неопределено); // ОписаниеОповещения.
	Параметры.Вставить("НепрерывноеВыполнение", НепрерывноеВыполнение);
	
	// Внутренние параметры.
	Параметры.Вставить("ОповещениеЗавершения", ОповещениеЗавершения);
	Параметры.Вставить("ОбработкаЗавершения", Новый ОписаниеОповещения(
		"ДействияПриНачалеРаботыСистемыОбработкаЗавершения", ЭтотОбъект));
	
	// Подготовка перехода к следующей процедуре.
	Параметры.Вставить("ОбработкаПродолжения", Новый ОписаниеОповещения(
		"ДействияПриНачалеРаботыСистемыВИнтеграционнойПроцедуре", ЭтотОбъект));
	
	Если Не ЗапускПрограммыЗавершен() Тогда
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Возникла непредвиденная ситуация при запуске программы.
			           |
			           |Техническая информация:
			           |Недопустимый вызов %1 при запуске программы. Сначала должна быть завершена процедура %2.
			           |Предположительно, один из обработчиков события не вызвал оповещение для продолжения.
			           |Последняя вызванная процедура %3.'"),
			"СтандартныеПодсистемыКлиент.ПриНачалеРаботыСистемы",
			"СтандартныеПодсистемыКлиент.ПередНачаломРаботыСистемы",
			ПолноеИмяПоследнейПроцедурыПередНачаломРаботыСистемы());
		Попытка
			ВызватьИсключение ТекстОшибки;
		Исключение
			ОбработатьОшибкуПриНачалеРаботыСистемы(Параметры, ИнформацияОбОшибке(), Истина);
		КонецПопытки;
		Если ИнтерактивнаяОбработкаПриНачалеРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
	КонецЕсли;
	
	Попытка
		УстановитьРасширенныйЗаголовокПриложения(Истина); // Для главного окна.
		
		Если НЕ ОбработатьПараметрыЗапуска() Тогда
			Параметры.Отказ = Истина;
			ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения);
			Возврат;
		КонецЕсли;
	Исключение
		ОбработатьОшибкуПриНачалеРаботыСистемы(Параметры, ИнформацияОбОшибке(), Истина);
	КонецПопытки;
	Если ИнтерактивнаяОбработкаПриНачалеРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПриНачалеРаботыСистемы.
Процедура ДействияПриНачалеРаботыСистемыВИнтеграционнойПроцедуре(Неопределен, Контекст) Экспорт
	
	Параметры = ПараметрыОбработкиПриНачалеРаботыСистемы();
	
	Если Не ПродолжитьДействияПриНачалеРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.Вставить("ОбработкаПродолжения", Новый ОписаниеОповещения(
		"ДействияПриНачалеРаботыСистемыВМодуляхИнтеграционнойПроцедуры", ЭтотОбъект));
	
	Параметры.Вставить("ИндексТекущегоМодуля", 0);
	Параметры.Вставить("ДобавленныеМодули", Новый Массив);
	Попытка
		Параметры.Вставить("Модули", Новый Массив);
		ИнтеграцияПодсистемБСПКлиент.ПриНачалеРаботыСистемы(Параметры);
		Параметры.Вставить("ДобавленныеМодули", Параметры.Модули);
		Параметры.Удалить("Модули");
	Исключение
		ОбработатьОшибкуПриНачалеРаботыСистемы(Параметры, ИнформацияОбОшибке());
	КонецПопытки;
	Если ИнтерактивнаяОбработкаПриНачалеРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПриНачалеРаботыСистемы.
Процедура ДействияПриНачалеРаботыСистемыВМодуляхИнтеграционнойПроцедуры(Неопределен, Контекст) Экспорт
	
	Пока Истина Цикл
		Параметры = ПараметрыОбработкиПриНачалеРаботыСистемы();
		
		Если Не ПродолжитьДействияПриНачалеРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		
		Если Параметры.ИндексТекущегоМодуля >= Параметры.ДобавленныеМодули.Количество() Тогда
			ДействияПриНачалеРаботыСистемыВПереопределяемойПроцедуре(Неопределено, Неопределено);
			Возврат;
		КонецЕсли;
		
		ОписаниеМодуля = Параметры.ДобавленныеМодули[Параметры.ИндексТекущегоМодуля];
		Параметры.ИндексТекущегоМодуля = Параметры.ИндексТекущегоМодуля + 1;
		
		Попытка
			Если ТипЗнч(ОписаниеМодуля) <> Тип("Структура") Тогда
				ТекущийМодуль = ОписаниеМодуля;
				ТекущийМодуль.ПриНачалеРаботыСистемы(Параметры);
			Иначе
				ТекущийМодуль = ОписаниеМодуля.Модуль;
				Если ОписаниеМодуля.Номер = 2 Тогда
					ТекущийМодуль.ПриНачалеРаботыСистемы2(Параметры);
				ИначеЕсли ОписаниеМодуля.Номер = 3 Тогда
					ТекущийМодуль.ПриНачалеРаботыСистемы3(Параметры);
				ИначеЕсли ОписаниеМодуля.Номер = 4 Тогда
					ТекущийМодуль.ПриНачалеРаботыСистемы4(Параметры);
				КонецЕсли;
			КонецЕсли;
		Исключение
			ОбработатьОшибкуПриНачалеРаботыСистемы(Параметры, ИнформацияОбОшибке());
		КонецПопытки;
		Если ИнтерактивнаяОбработкаПриНачалеРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПриНачалеРаботыСистемы.
Процедура ДействияПриНачалеРаботыСистемыВПереопределяемойПроцедуре(Неопределен, Контекст)
	
	Параметры = ПараметрыОбработкиПриНачалеРаботыСистемы();
	
	Если Не ПродолжитьДействияПриНачалеРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.Вставить("ОбработкаПродолжения", Новый ОписаниеОповещения(
		"ДействияПриНачалеРаботыСистемыВМодуляхПереопределяемойПроцедуры", ЭтотОбъект));
	
	Параметры.Вставить("ИндексТекущегоМодуля", 0);
	Параметры.Вставить("ДобавленныеМодули", Новый Массив);
	Попытка
		Параметры.Вставить("Модули", Новый Массив);
		ОбщегоНазначенияКлиентПереопределяемый.ПриНачалеРаботыСистемы(Параметры);
		Параметры.Вставить("ДобавленныеМодули", Параметры.Модули);
		Параметры.Удалить("Модули");
	Исключение
		ОбработатьОшибкуПриНачалеРаботыСистемы(Параметры, ИнформацияОбОшибке());
	КонецПопытки;
	Если ИнтерактивнаяОбработкаПриНачалеРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПриНачалеРаботыСистемы.
Процедура ДействияПриНачалеРаботыСистемыВМодуляхПереопределяемойПроцедуры(Неопределен, Контекст) Экспорт
	
	Пока Истина Цикл
		
		Параметры = ПараметрыОбработкиПриНачалеРаботыСистемы();
		
		Если Не ПродолжитьДействияПриНачалеРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		
		Если Параметры.ИндексТекущегоМодуля >= Параметры.ДобавленныеМодули.Количество() Тогда
			ДействияПриНачалеРаботыСистемыПослеВсехПроцедур(Неопределено, Неопределено);
			Возврат;
		КонецЕсли;
		
		ТекущийМодуль = Параметры.ДобавленныеМодули[Параметры.ИндексТекущегоМодуля];
		Параметры.ИндексТекущегоМодуля = Параметры.ИндексТекущегоМодуля + 1;
		
		Попытка
			ТекущийМодуль.ПриНачалеРаботыСистемы(Параметры);
		Исключение
			ОбработатьОшибкуПриНачалеРаботыСистемы(Параметры, ИнформацияОбОшибке());
		КонецПопытки;
		Если ИнтерактивнаяОбработкаПриНачалеРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПриНачалеРаботыСистемы.
Процедура ДействияПриНачалеРаботыСистемыПослеВсехПроцедур(Неопределен, Контекст)
	
	Параметры = ПараметрыОбработкиПриНачалеРаботыСистемы();
	
	Если Не ПродолжитьДействияПриНачалеРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.Вставить("ОбработкаПродолжения", Параметры.ОбработкаЗавершения);
	
	Попытка
		ИнтеграцияПодсистемБСПКлиент.ПослеНачалаРаботыСистемы();
		ОбщегоНазначенияКлиентПереопределяемый.ПослеНачалаРаботыСистемы();
	Исключение
		ОбработатьОшибкуПриНачалеРаботыСистемы(Параметры, ИнформацияОбОшибке());
	КонецПопытки;
	Если ИнтерактивнаяОбработкаПриНачалеРаботыСистемы(Параметры) Тогда
		Возврат;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Завершение процедуры ПриНачалеРаботыСистемы.
Процедура ДействияПриНачалеРаботыСистемыОбработкаЗавершения(Неопределен, Контекст) Экспорт
	
	Параметры = ПараметрыОбработкиПриНачалеРаботыСистемы(Истина);
	
	Параметры.ОбработкаПродолжения = Неопределено;
	Параметры.ОбработкаЗавершения  = Неопределено;
	
	Если НЕ Параметры.Отказ Тогда
		ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"];
		Если ПараметрыПриЗапускеПрограммы.Свойство("ПропуститьОчисткуСкрытияРабочегоСтола") Тогда
			ПараметрыПриЗапускеПрограммы.Удалить("ПропуститьОчисткуСкрытияРабочегоСтола");
		КонецЕсли;
		СкрытьРабочийСтолПриНачалеРаботыСистемы(Ложь);
	КонецЕсли;
	
	Если Параметры.ОповещениеЗавершения <> Неопределено Тогда
		
		Результат = Новый Структура;
		Результат.Вставить("Отказ", Параметры.Отказ);
		Результат.Вставить("Перезапустить", Параметры.Перезапустить);
		Результат.Вставить("ДополнительныеПараметрыКоманднойСтроки", Параметры.ДополнительныеПараметрыКоманднойСтроки);
		ВыполнитьОбработкуОповещения(Параметры.ОповещениеЗавершения, Результат);
		Возврат;
		
	Иначе
		Если Параметры.Отказ Тогда
			Если Параметры.Перезапустить <> Истина Тогда
				ПрекратитьРаботуСистемы();
				
			ИначеЕсли ЗначениеЗаполнено(Параметры.ДополнительныеПараметрыКоманднойСтроки) Тогда
				ПрекратитьРаботуСистемы(Параметры.Перезапустить, Параметры.ДополнительныеПараметрыКоманднойСтроки);
			Иначе
				ПрекратитьРаботуСистемы(Параметры.Перезапустить);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования.
Функция ПараметрыОбработкиПриНачалеРаботыСистемы(Удалить = Ложь)
	
	ИмяПараметра = "СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы";
	Свойства = ПараметрыПриложения[ИмяПараметра];
	Если Свойства = Неопределено Тогда
		Свойства = Новый Структура;
		ПараметрыПриложения.Вставить(ИмяПараметра, Свойства);
	КонецЕсли;
	
	ИмяСвойства = "ПараметрыОбработкиПриНачалеРаботыСистемы";
	Если Свойства.Свойство(ИмяСвойства) Тогда
		Параметры = Свойства[ИмяСвойства];
	Иначе
		Параметры = Новый Структура;
		Свойства.Вставить(ИмяСвойства, Параметры);
	КонецЕсли;
	
	Если Удалить Тогда
		Свойства.Удалить(ИмяСвойства);
	КонецЕсли;
	
	Возврат Параметры;
	
КонецФункции

// Обработать параметры запуска программы.
//
// Возвращаемое значение:
//   Булево   - Истина, если необходимо прервать выполнение процедуры ПриНачалеРаботыСистемы.
//
Функция ОбработатьПараметрыЗапуска()

	Если ПустаяСтрока(ПараметрЗапуска) Тогда
		Возврат Истина;
	КонецЕсли;
	
	// Параметр может состоять из частей, разделенных символом ";".
	ПараметрыЗапуска = СтрРазделить(ПараметрЗапуска, ";", Ложь);
	
	Отказ = Ложь;
	ИнтеграцияПодсистемБСПКлиент.ПриОбработкеПараметровЗапуска(ПараметрыЗапуска, Отказ);
	ОбщегоНазначенияКлиентПереопределяемый.ПриОбработкеПараметровЗапуска(ПараметрыЗапуска, Отказ);
	
	Возврат Не Отказ;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// ПередЗавершениемРаботыСистемы

// Только для внутреннего использования. 
// 
// Параметры:
//  Пересоздать - Булево
//
// Возвращаемое значение:
//   Структура:
//     Отказ - Булево
//     Предупреждения - Массив из см. СтандартныеПодсистемыКлиент.ПредупреждениеПриЗавершенииРаботы.
//     ИнтерактивнаяОбработка - ОписаниеОповещения, Неопределено
//     ОбработкаПродолжения - ОписаниеОповещения, Неопределено
//     НепрерывноеВыполнение - Булево
//     ОбработкаЗавершения - ОписаниеОповещения
//
Функция ПараметрыДействийПередЗавершениемРаботыСистемы(Пересоздать = Ложь) Экспорт
	
	ИмяПараметра = "СтандартныеПодсистемы.ПараметрыДействийПередЗавершениемРаботыСистемы";
	Если Пересоздать Или ПараметрыПриложения[ИмяПараметра] = Неопределено Тогда
		ПараметрыПриложения.Вставить(ИмяПараметра, Новый Структура);
	КонецЕсли;
	Параметры = ПараметрыПриложения[ИмяПараметра];
	
	Если Не Пересоздать Тогда
		Возврат Параметры;
	КонецЕсли;
	
	// Внешние параметры описания результата.
	Параметры.Вставить("Отказ", Ложь);
	Параметры.Вставить("Предупреждения", ПараметрКлиента("ПредупрежденияПриЗавершенииРаботы"));
	
	// Внешние параметры управления выполнением.
	Параметры.Вставить("ИнтерактивнаяОбработка", Неопределено); // ОписаниеОповещения.
	Параметры.Вставить("ОбработкаПродолжения",   Неопределено); // ОписаниеОповещения.
	Параметры.Вставить("НепрерывноеВыполнение", Истина);
	
	// Внутренние параметры.
	Параметры.Вставить("ОбработкаЗавершения", Новый ОписаниеОповещения(
		"ДействияПередЗавершениемРаботыСистемыОбработкаЗавершения", СтандартныеПодсистемыКлиент));
	Возврат Параметры;
	
КонецФункции	
	
// Только для внутреннего использования. Продолжение процедуры ПередЗавершениемРаботыСистемы.
//
// Параметры:
//   Параметры - см. СтандартныеПодсистемыКлиент.ПараметрыДействийПередЗавершениемРаботыСистемы
//
Процедура ДействияПередЗавершениемРаботыСистемы(Параметры) Экспорт
	
	Параметры.Вставить("ОбработкаПродолжения", Параметры.ОбработкаЗавершения);
	
	Если ОбщегоНазначенияКлиент.ДоступноИспользованиеРазделенныхДанных() Тогда
		Попытка
			ОткрытьФормуПредупрежденийПриЗавершенииРаботы(Параметры);
		Исключение
			ОбработатьОшибкуПриЗапускеИлиЗавершении(Параметры, ИнформацияОбОшибке(), "Завершение");
		КонецПопытки;
		Если ИнтерактивнаяОбработкаПередЗавершениемРаботыСистемы(Параметры) Тогда
			Возврат;
		КонецЕсли;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Завершение процедуры ПередЗавершениемРаботыСистемы.
//
// Параметры:
//   Неопределен - Неопределено
//   Параметры - см. СтандартныеПодсистемыКлиент.ПараметрыДействийПередЗавершениемРаботыСистемы
//
Процедура ДействияПередЗавершениемРаботыСистемыОбработкаЗавершения(Неопределен, Параметры) Экспорт
	
	Параметры = ПараметрыДействийПередЗавершениемРаботыСистемы();
	Параметры.ОбработкаПродолжения = Неопределено;
	Параметры.ОбработкаЗавершения  = Неопределено;
	ИмяПараметра = "СтандартныеПодсистемы.ПропуститьЗавершениеРаботыСистемыПослеОбработкиПредупреждений";
	
	Если Не Параметры.Отказ
	   И Не Параметры.НепрерывноеВыполнение
	   И ПараметрыПриложения.Получить(ИмяПараметра) = Неопределено Тогда
		
		ИмяПараметра = "СтандартныеПодсистемы.ПропуститьПредупреждениеПередЗавершениемРаботыСистемы";
		ПараметрыПриложения.Вставить(ИмяПараметра, Истина);
		ЗавершитьРаботуСистемы();
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования. Завершение процедуры ПередЗавершениемРаботыСистемы.
// 
// Параметры:
//  Неопределен - Неопределено
//  ОбработкаПродолжения - ОписаниеОповещения
//
Процедура ДействияПередЗавершениемРаботыСистемыПослеОбработкиОшибки(Неопределен, ОбработкаПродолжения) Экспорт
	
	Параметры = ПараметрыДействийПередЗавершениемРаботыСистемы();
	Параметры.ОбработкаПродолжения = ОбработкаПродолжения;
	
	Если Параметры.Отказ Тогда
		Параметры.Отказ = Ложь;
		ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения);
	Иначе
		ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	КонецЕсли;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Прочие процедуры и функции для запуска и завершения работы программы.

// См. ОбщегоНазначенияКлиентПереопределяемый.ПередНачаломРаботыСистемы.
Процедура ПередНачаломРаботыСистемы2(Параметры) Экспорт
	
	// Проверяет минимально допустимую версию платформы для запуска.
	// Если версия платформы более поздняя, чем РекомендуемаяВерсияПлатформы,
	// то пользователю будет  показано оповещение. Работа программы будет прекращена,
	// если ПараметрыКлиента.РаботаВПрограммеЗапрещена = Истина.
	
	ПараметрыКлиента = ПараметрыРаботыКлиентаПриЗапуске();
	
	Если ПараметрыКлиента.Свойство("ПоказатьНерекомендуемуюВерсиюПлатформы") Тогда
		Параметры.ИнтерактивнаяОбработка = Новый ОписаниеОповещения(
			"ПроверитьВерсиюПлатформыПриЗапуске", ЭтотОбъект);
	ИначеЕсли ПараметрыКлиента.Свойство("ИспользуетсяНедопустимаяВерсияПлатформы") Тогда
		Параметры.ИнтерактивнаяОбработка = Новый ОписаниеОповещения(
			"ПредупредитьОНедопустимойВерсииПлатформы", ЭтотОбъект);
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы2.
Процедура ПроверитьВерсиюПлатформыПриЗапуске(Параметры, Контекст) Экспорт
	
	ПараметрыКлиента = ПараметрыРаботыКлиентаПриЗапуске();
	
	СистемнаяИнформация = Новый СистемнаяИнформация;
	Текущая             = СистемнаяИнформация.ВерсияПриложения;
	Минимальная         = ПараметрыКлиента.МинимальнаяВерсияПлатформы;
	Если СтрНайти(ПараметрЗапуска, "ВыполнитьОбновлениеИЗавершитьРаботу") > 0
		И ОбщегоНазначенияКлиентСервер.СравнитьВерсии(Текущая, Минимальная) < 0
		И ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.ОбновлениеКонфигурации") Тогда
		ТекстСообщения =
			НСтр("ru = 'Выполнение обновления программы невозможно
				|Предварительно обновите версию платформы 1С:Предприятие.
				|Используемая версия платформы - %1.
				|Минимально необходимая версия платформы - %2'");
		ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСообщения, Текущая, Минимальная);
		МодульОбновлениеКонфигурацииКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ОбновлениеКонфигурацииКлиент");
		МодульОбновлениеКонфигурацииКлиент.ЗаписатьОшибкуНеобходимостиОбновленияПлатформы(ТекстСообщения);
	КонецЕсли;
	
	ОповещениеОЗакрытии = Новый ОписаниеОповещения("ПослеЗакрытияФормыНерекомендуемойВерсииПлатформы", ЭтотОбъект, Параметры);
	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("ИнтернетПоддержкаПользователей.ПолучениеОбновленийПрограммы") Тогда
		СтандартнаяОбработка = Истина;
		МодульПолучениеОбновленийПрограммыКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ПолучениеОбновленийПрограммыКлиент");
		МодульПолучениеОбновленийПрограммыКлиент.ПриПроверкеВерсииПлатформыПриЗапуске(ОповещениеОЗакрытии, СтандартнаяОбработка);
		Если Не СтандартнаяОбработка Тогда
			Возврат;
		КонецЕсли;
	КонецЕсли;
	
	Если ОбщегоНазначенияКлиентСервер.СравнитьВерсии(Текущая, Минимальная) < 0 Тогда
		Если ПользователиКлиент.ЭтоПолноправныйПользователь(Истина) Тогда
			ТекстСообщения =
				НСтр("ru = 'Вход в программу невозможен.
				           |Предварительно обновите версию платформы 1С:Предприятие.'");
		Иначе
			ТекстСообщения =
				НСтр("ru = 'Вход в программу невозможен.
				           |Обратитесь к администратору для обновления версии платформы 1С:Предприятие.'");
		КонецЕсли;
	Иначе
		Если ПользователиКлиент.ЭтоПолноправныйПользователь(Истина) Тогда
			ТекстСообщения =
				НСтр("ru = 'Рекомендуется завершить работу программы и обновить версию платформы 1С:Предприятия.
				         |Новая версия платформы содержит исправления ошибок, которые позволят программе работать более стабильно.
				         |Вы также можете продолжить работу на текущей версии.
				         |Минимально необходимая версия платформы %1.'");
		Иначе
			ТекстСообщения = 
				НСтр("ru = 'Рекомендуется завершить работу программы и обратиться к администратору для обновления версии платформы 1С:Предприятия.
				         |Новая версия платформы содержит исправления ошибок, которые позволят программе работать более стабильно.
				         |Вы также можете продолжить работу на текущей версии.
				         |Минимально необходимая версия платформы %1.'");
		КонецЕсли;
	КонецЕсли;
	
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("ТекстСообщения", ТекстСообщения);
	ПараметрыФормы.Вставить("РекомендуемаяВерсияПлатформы", ПараметрыКлиента.РекомендуемаяВерсияПлатформы);
	ПараметрыФормы.Вставить("МинимальнаяВерсияПлатформы", ПараметрыКлиента.МинимальнаяВерсияПлатформы);
	ПараметрыФормы.Вставить("ОткрытаПоСценарию", Истина);
	ПараметрыФормы.Вставить("ПропуститьЗавершениеРаботы", Истина);
	
	Форма = ОткрытьФорму("Обработка.НерекомендуемаяВерсияПлатформы.Форма.НерекомендуемаяВерсияПлатформы", ПараметрыФормы,
		, , , , ОповещениеОЗакрытии);	
	Если Форма = Неопределено Тогда
		ПослеЗакрытияФормыНерекомендуемойВерсииПлатформы("Продолжить", Параметры);
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПроверитьВерсиюПлатформыПриЗапуске.
Процедура ПослеЗакрытияФормыНерекомендуемойВерсииПлатформы(Результат, Параметры) Экспорт
	
	Если Результат <> "Продолжить" Тогда
		Параметры.Отказ = Истина;
	Иначе
		Параметры.ПолученныеПараметрыКлиента.Вставить("ПоказатьНерекомендуемуюВерсиюПлатформы");
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы2.
Процедура ПредупредитьОНедопустимойВерсииПлатформы(Параметры, Контекст) Экспорт

	ОповещениеОЗакрытии = Новый ОписаниеОповещения("ПослеЗакрытияФормыНедопустимойВерсииПлатформы", ЭтотОбъект, Параметры);
	
	Форма = ОткрытьФорму("Обработка.НерекомендуемаяВерсияПлатформы.Форма.НеобходимоОбновитьПлатформу", ,
		, , , , ОповещениеОЗакрытии); 
	
	Если Форма = Неопределено Тогда
		ПослеЗакрытияФормыНедопустимойВерсииПлатформы("Продолжить", Параметры);
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПроверитьВерсиюПлатформыПриЗапуске.
Процедура ПослеЗакрытияФормыНедопустимойВерсииПлатформы(Результат, Параметры) Экспорт
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// См. ОбщегоНазначенияКлиентПереопределяемый.ПередНачаломРаботыСистемы.
Процедура ПередНачаломРаботыСистемы3(Параметры) Экспорт
	
	// Проверяет необходимость восстановления связи с главным узлом и
	// начинает восстановление, если требуется.
	
	ПараметрыКлиента = ПараметрыРаботыКлиентаПриЗапуске();
	
	Если НЕ ПараметрыКлиента.Свойство("ВосстановитьСвязьСГлавнымУзлом") Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.ИнтерактивнаяОбработка = Новый ОписаниеОповещения(
		"ИнтерактивнаяОбработкаВосстановленияСвязиСГлавнымУзлом", ЭтотОбъект);
	
КонецПроцедуры

// См. ОбщегоНазначенияКлиентПереопределяемый.ПередНачаломРаботыСистемы.
Процедура ПередНачаломРаботыСистемы4(Параметры) Экспорт
	
	// Проверяет необходимость установки основного языка и часового пояса
	// информационной базы и открывает форму региональных настроек, если требуется.
	
	ПараметрыКлиента = ПараметрыРаботыКлиентаПриЗапуске();
	
	Если Не ПараметрыКлиента.Свойство("ВыбратьНачальныеРегиональныеНастройкиИБ") Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.ИнтерактивнаяОбработка = Новый ОписаниеОповещения(
		"ИнтерактивнаяОбработкаНачальныхРегиональныхНастроекИБ", ЭтотОбъект, Параметры);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПроверитьНеобходимостьВосстановленияСвязиСГлавнымУзлом.
Процедура ИнтерактивнаяОбработкаВосстановленияСвязиСГлавнымУзлом(Параметры, Контекст) Экспорт
	
	ПараметрыКлиента = ПараметрыРаботыКлиентаПриЗапуске();
	
	Если ПараметрыКлиента.ВосстановитьСвязьСГлавнымУзлом = Ложь Тогда
		Параметры.Отказ = Истина;
		ПоказатьПредупреждение(
			ОповещениеБезРезультата(Параметры.ОбработкаПродолжения),
			НСтр("ru = 'Вход в программу временно невозможен до восстановления связи с главным узлом.
			           |Обратитесь к администратору за подробностями.'"),
			15);
		Возврат;
	КонецЕсли;
	
	Форма = ОткрытьФорму("ОбщаяФорма.ВосстановлениеСвязиСГлавнымУзлом",,,,,,
		Новый ОписаниеОповещения("ПослеЗакрытияФормыВосстановленияСвязиСГлавнымУзлом", ЭтотОбъект, Параметры));
	
	Если Форма = Неопределено Тогда
		ПослеЗакрытияФормыВосстановленияСвязиСГлавнымУзлом(Новый Структура("Отказ", Истина), Параметры);
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы4.
Процедура ИнтерактивнаяОбработкаНачальныхРегиональныхНастроекИБ(Параметры, Контекст) Экспорт
	
	ПараметрыКлиента = ПараметрыРаботыКлиентаПриЗапуске();
	
	Если ПараметрыКлиента.ВыбратьНачальныеРегиональныеНастройкиИБ = Ложь Тогда
		Параметры.Отказ = Истина;
		ПоказатьПредупреждение(
			ОповещениеБезРезультата(Параметры.ОбработкаПродолжения),
			НСтр("ru = 'Вход в программу невозможен до установки начальных региональных настроек программы.
			           |Обратитесь к администратору за подробностями.'"),
			15);
		Возврат;
	КонецЕсли;
	
	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.Мультиязычность") Тогда
		МодульМультиязычностьКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("МультиязычностьКлиент");
		ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияФормыВыбораНачальныхРегиональныхНастроекИБ", ЭтотОбъект, Параметры);
		МодульМультиязычностьКлиент.ОткрытьФормуРегиональныхНастроек(ОписаниеОповещения);
	Иначе
		ПослеЗакрытияФормыВыбораНачальныхРегиональныхНастроекИБ(Новый Структура("Отказ", Истина), Параметры);
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПроверитьНеобходимостьВосстановленияСвязиСГлавнымУзлом.
Процедура ПослеЗакрытияФормыВосстановленияСвязиСГлавнымУзлом(Результат, Параметры) Экспорт
	
	Если ТипЗнч(Результат) <> Тип("Структура") Или Результат.Отказ Тогда
		Параметры.Отказ = Истина;
	Иначе
		Параметры.ПолученныеПараметрыКлиента.Вставить("ВосстановитьСвязьСГлавнымУзлом");
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Только для внутреннего использования. Продолжение процедуры ПередНачаломРаботыСистемы4.
Процедура ПослеЗакрытияФормыВыбораНачальныхРегиональныхНастроекИБ(Результат, Параметры) Экспорт
	
	Если ТипЗнч(Результат) <> Тип("Структура") Или Результат.Отказ Тогда
		Параметры.Отказ = Истина;
	Иначе
		Параметры.ПолученныеПараметрыКлиента.Вставить("ВыбратьНачальныеРегиональныеНастройкиИБ");
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Устанавливает флаг скрытия рабочего стола при начале работы системы,
// который блокирует создание форм на рабочем столе.
// Снимает флаг скрытия и обновляет рабочий стол, когда это станет возможным,
// если скрытие выполнялось.
//
// Параметры:
//  Скрыть - Булево - если передать Ложь, тогда при условии скрытия рабочего
//           стола он будет вновь показан.
//
//  УжеВыполненоНаСервере - Булево - если передать Истина, тогда уже был вызван
//           метод в модуле СтандартныеПодсистемыВызовСервера, и его не требуется
//           вызвать, а требуется только установить на клиенте, что рабочий стол
//           был скрыт и позднее его требуется показать.
//
Процедура СкрытьРабочийСтолПриНачалеРаботыСистемы(Скрыть = Истина, УжеВыполненоНаСервере = Ложь) Экспорт
	
	ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"];
	
	Если Скрыть Тогда
		Если НЕ ПараметрыПриЗапускеПрограммы.Свойство("СкрытьРабочийСтолПриНачалеРаботыСистемы") Тогда
			ПараметрыПриЗапускеПрограммы.Вставить("СкрытьРабочийСтолПриНачалеРаботыСистемы");
			Если НЕ УжеВыполненоНаСервере Тогда
				СтандартныеПодсистемыВызовСервера.СкрытьРабочийСтолПриНачалеРаботыСистемы();
			КонецЕсли;
			ОбновитьИнтерфейс();
		КонецЕсли;
	Иначе
		Если ПараметрыПриЗапускеПрограммы.Свойство("СкрытьРабочийСтолПриНачалеРаботыСистемы") Тогда
			ПараметрыПриЗапускеПрограммы.Удалить("СкрытьРабочийСтолПриНачалеРаботыСистемы");
			Если НЕ УжеВыполненоНаСервере Тогда
				СтандартныеПодсистемыВызовСервера.СкрытьРабочийСтолПриНачалеРаботыСистемы(Ложь);
			КонецЕсли;
			ОбщегоНазначенияКлиент.ОбновитьИнтерфейсПрограммы();
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура ВыполнитьОповещениеСПустымРезультатом(ОповещениеСРезультатом) Экспорт
	
	ВыполнитьОбработкуОповещения(ОповещениеСРезультатом);
	
КонецПроцедуры

// Только для внутреннего использования.
Процедура НачатьИнтерактивнуюОбработкуПередЗавершениемРаботыСистемы() Экспорт
	
	ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"];
	Если НЕ ПараметрыПриЗапускеПрограммы.Свойство("ПараметрыОбработкиЗавершения") Тогда
		Возврат;
	КонецЕсли;
	
	Параметры = ПараметрыПриЗапускеПрограммы.ПараметрыОбработкиЗавершения;
	ПараметрыПриЗапускеПрограммы.Удалить("ПараметрыОбработкиЗавершения");
	
	ИнтерактивнаяОбработка = Параметры.ИнтерактивнаяОбработка;
	Параметры.ИнтерактивнаяОбработка = Неопределено;
	ВыполнитьОбработкуОповещения(ИнтерактивнаяОбработка, Параметры);
	
КонецПроцедуры

// Только для внутреннего использования.
//
// Параметры:
//  Результат - КодВозвратаДиалога 
//            - Неопределено
//  ДополнительныеПараметры - Структура
//
Процедура ПослеЗакрытияФормыПредупрежденийПриЗавершенииРаботы(Результат, ДополнительныеПараметры) Экспорт
	
	Параметры = ПараметрыДействийПередЗавершениемРаботыСистемы();
	
	Если ДополнительныеПараметры.ВариантФормы = "Вопрос" Тогда
		
		Если Результат = Неопределено Или Результат.Значение <> КодВозвратаДиалога.Да Тогда
			Параметры.Отказ = Истина;
		КонецЕсли;
		
	ИначеЕсли ДополнительныеПараметры.ВариантФормы = "СтандартнаяФорма" Тогда
	
		Если Результат = Истина Или Результат = Неопределено Тогда
			Параметры.Отказ = Истина;
		КонецЕсли;
		
	Иначе // ПрикладнаяФорма
		Если Результат = Истина Или Результат = Неопределено Или Результат = КодВозвратаДиалога.Нет Тогда
			Параметры.Отказ = Истина;
		КонецЕсли;
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// См. ОбщегоНазначенияКлиентПереопределяемый.ПослеНачалаРаботыСистемы.
Процедура ПослеНачалаРаботыСистемы() Экспорт
	
	Если ТребуетсяПоказРекомендацииПоОбъемуОперативнойПамяти() Тогда
		ПодключитьОбработчикОжидания("ПоказатьРекомендациюПоОбъемуОперативнойПамяти", 10, Истина);
	КонецЕсли;
	
	Если ВыводитьПредупрежденияПередЗавершениемРаботыСистемы(Ложь) Тогда
		// Предварительная компиляция клиентских модулей для избежания неявных серверных вызовов
		// в обработчике ПередЗавершениемРаботыСистемы.
		ПредупрежденияПередЗавершениемРаботыСистемы(Ложь); 
	КонецЕсли;
	
КонецПроцедуры

Функция ВыводитьПредупрежденияПередЗавершениемРаботыСистемы(Отказ)
	
	Если ОтключенаЛогикаНачалаРаботыСистемы() Тогда
		Возврат Ложь;
	КонецЕсли;
	
	ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"];
	
	Если ПараметрыПриЗапускеПрограммы.Свойство("СкрытьРабочийСтолПриНачалеРаботыСистемы") Тогда
		// Произошла попытка закрытия до окончания запуска.
		// В веб-клиенте это возможно в штатном случае (при закрытии страницы в целом),
		// поэтому закрытие блокируется, так как его все равно можно выполнить принудительно,
		// а в случае случайного закрытия у пользователя должна быть возможность остаться на странице.
		// Не в веб-клиенте это возможно в случае ошибок в немодальной последовательности запуска.
		// То есть нет ни одного окна блокирующего весь интерфейс. Закрытие нужно разрешить,
		// но без стандартных процедур перед завершение работы системы, так как они могут
		// привести к ошибке в процессе закрытия из-за незавершенного запуска.
#Если Не ВебКлиент Тогда
		Отказ = Истина;
#КонецЕсли
		Возврат Ложь;
	КонецЕсли;
	
	// В режиме работы толстый клиент (обычное приложение) не выводится список предупреждений.
#Если ТолстыйКлиентОбычноеПриложение Тогда
	Возврат Ложь;
#КонецЕсли
	
	Если ПараметрыПриложения["СтандартныеПодсистемы.ПропуститьПредупреждениеПередЗавершениемРаботыСистемы"] = Истина Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если Не ОбщегоНазначенияКлиент.ДоступноИспользованиеРазделенныхДанных() Тогда
		Возврат Ложь;
	КонецЕсли;
	Возврат Истина;
	
КонецФункции
	
Функция ПредупрежденияПередЗавершениемРаботыСистемы(Отказ)
	
	Предупреждения = Новый Массив;
	ИнтеграцияПодсистемБСПКлиент.ПередЗавершениемРаботыСистемы(Отказ, Предупреждения);
	ОбщегоНазначенияКлиентПереопределяемый.ПередЗавершениемРаботыСистемы(Отказ, Предупреждения);
	Возврат Предупреждения;

КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Для справочника ИдентификаторыОбъектовМетаданных.

// Только для внутреннего использования.
Процедура ИдентификаторыОбъектовМетаданныхФормаСпискаСписокВыборЗначения(Форма, Элемент, Значение, СтандартнаяОбработка) Экспорт
	
	Если Не Форма.ВыбиратьГруппыОбъектовМетаданных
	   И Элемент.ТекущиеДанные <> Неопределено
	   И Не Элемент.ТекущиеДанные.ПометкаУдаления
	   И Не ЗначениеЗаполнено(Элемент.ТекущиеДанные.Родитель) Тогда
		
		СтандартнаяОбработка = Ложь;
		
		Если Элемент.Отображение = ОтображениеТаблицы.Дерево Тогда
			Если Элемент.Развернут(Элемент.ТекущаяСтрока) Тогда
				Элемент.Свернуть(Элемент.ТекущаяСтрока);
			Иначе
				Элемент.Развернуть(Элемент.ТекущаяСтрока);
			КонецЕсли;
			
		ИначеЕсли Элемент.Отображение = ОтображениеТаблицы.ИерархическийСписок Тогда
			
			Если Элемент.ТекущийРодитель <> Элемент.ТекущаяСтрока Тогда
				Элемент.ТекущийРодитель = Элемент.ТекущаяСтрока;
			Иначе
				ТекущаяСтрока = Элемент.ТекущаяСтрока;
				Элемент.ТекущийРодитель = Неопределено;
				Элемент.ТекущаяСтрока = ТекущаяСтрока;
			КонецЕсли;
		Иначе
			ПоказатьПредупреждение(,
				НСтр("ru = 'Невозможно выбрать группу объектов метаданных.
				           |Выберите объект метаданных.'"));
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

#Область ПараметрыРаботыКлиентаНаСервере

Процедура ЗаполнитьПараметрыРаботыКлиентаНаСервере(Параметры) Экспорт
	
	Параметры.Вставить("ПараметрЗапуска", ПараметрЗапуска);
	Параметры.Вставить("СтрокаСоединенияИнформационнойБазы", СтрокаСоединенияИнформационнойБазы());
	Параметры.Вставить("ЭтоВебКлиент", ЭтоВебКлиент());
	Параметры.Вставить("ЭтоLinuxКлиент", ОбщегоНазначенияКлиент.ЭтоLinuxКлиент());
	Параметры.Вставить("ЭтоMacOSКлиент", ОбщегоНазначенияКлиент.ЭтоMacOSКлиент());
	Параметры.Вставить("ЭтоWindowsКлиент", ОбщегоНазначенияКлиент.ЭтоWindowsКлиент());
	Параметры.Вставить("ЭтоМобильныйКлиент", ЭтоМобильныйКлиент());
	Параметры.Вставить("ИспользуемыйКлиент", ИспользуемыйКлиент());
	Параметры.Вставить("КаталогПрограммы", ТекущийКаталогПрограммы());
	Параметры.Вставить("ИдентификаторКлиента", ИдентификаторКлиента());
	Параметры.Вставить("СкрытьРабочийСтолПриНачалеРаботыСистемы", Ложь);
	Параметры.Вставить("ОперативнаяПамять", ОбщегоНазначенияКлиент.ОперативнаяПамятьДоступнаяКлиентскомуПриложению());
	Параметры.Вставить("РазрешениеОсновногоЭкрана", РазрешениеОсновногоЭкрана());
	Параметры.Вставить("СистемнаяИнформация", СистемнаяИнформацияКлиента());
	
	// Установка даты клиента непосредственно перед вызовом, чтобы уменьшить погрешность.
	Параметры.Вставить("ТекущаяДатаНаКлиенте", ТекущаяДата()); // АПК:143 Требуется ТекущаяДата() для расчета ПоправкаКВремениСеанса
	Параметры.Вставить("ТекущаяУниверсальнаяДатаВМиллисекундахНаКлиенте", ТекущаяУниверсальнаяДатаВМиллисекундах());
	
КонецПроцедуры

// Возвращаемое значение:
//   см. ОбщегоНазначения.ИспользуемыйКлиент
//
Функция ИспользуемыйКлиент()
	
	ИспользуемыйКлиент = "";
	#Если ТонкийКлиент Тогда
		ИспользуемыйКлиент = "ТонкийКлиент";
	#ИначеЕсли ТолстыйКлиентУправляемоеПриложение Тогда
		ИспользуемыйКлиент = "ТолстыйКлиентУправляемоеПриложение";
	#ИначеЕсли ТолстыйКлиентОбычноеПриложение Тогда
		ИспользуемыйКлиент = "ТолстыйКлиентОбычноеПриложение";
	#ИначеЕсли ВебКлиент Тогда
		ОписаниеБраузера = ТекущийБраузер();
		Если ПустаяСтрока(ОписаниеБраузера.Версия) Тогда
			ИспользуемыйКлиент = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("ВебКлиент.%1", ОписаниеБраузера.Название);
		Иначе
			ИспользуемыйКлиент = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("ВебКлиент.%1.%2", ОписаниеБраузера.Название, СтрРазделить(ОписаниеБраузера.Версия, ".")[0]);
		КонецЕсли;
	#КонецЕсли
	
	Возврат ИспользуемыйКлиент;
	
КонецФункции

Функция ТекущийБраузер()
	
	Результат = Новый Структура("Название,Версия", "Другой", "");
	
	СистемнаяИнформация = Новый СистемнаяИнформация;
	Строка = СистемнаяИнформация.ИнформацияПрограммыПросмотра;
	Строка = СтрЗаменить(Строка, ",", ";");

	// Opera
	Идентификатор = "Opera";
	Позиция = СтрНайти(Строка, Идентификатор, НаправлениеПоиска.СКонца);
	Если Позиция > 0 Тогда
		Строка = Сред(Строка, Позиция + СтрДлина(Идентификатор));
		Результат.Название = "Opera";
		Идентификатор = "Version/";
		Позиция = СтрНайти(Строка, Идентификатор);
		Если Позиция > 0 Тогда
			Строка = Сред(Строка, Позиция + СтрДлина(Идентификатор));
			Результат.Версия = СокрЛП(Строка);
		Иначе
			Строка = СокрЛП(Строка);
			Если СтрНачинаетсяС(Строка, "/") Тогда
				Строка = Сред(Строка, 2);
			КонецЕсли;
			Результат.Версия = СокрЛ(Строка);
		КонецЕсли;
		Возврат Результат;
	КонецЕсли;

	// IE
	Идентификатор = "MSIE"; // v11-
	Позиция = СтрНайти(Строка, Идентификатор);
	Если Позиция > 0 Тогда
		Результат.Название = "IE";
		Строка = Сред(Строка, Позиция + СтрДлина(Идентификатор));
		Позиция = СтрНайти(Строка, ";");
		Если Позиция > 0 Тогда
			Строка = СокрЛ(Лев(Строка, Позиция - 1));
			Результат.Версия = Строка;
		КонецЕсли;
		Возврат Результат;
	КонецЕсли;

	Идентификатор = "Trident"; // v11+
	Позиция = СтрНайти(Строка, Идентификатор);
	Если Позиция > 0 Тогда
		Результат.Название = "IE";
		Строка = Сред(Строка, Позиция + СтрДлина(Идентификатор));
		
		Идентификатор = "rv:";
		Позиция = СтрНайти(Строка, Идентификатор);
		Если Позиция > 0 Тогда
			Строка = Сред(Строка, Позиция + СтрДлина(Идентификатор));
			Позиция = СтрНайти(Строка, ")");
			Если Позиция > 0 Тогда
				Строка = СокрЛ(Лев(Строка, Позиция - 1));
				Результат.Версия = Строка;
			КонецЕсли;
		КонецЕсли;
		Возврат Результат;
	КонецЕсли;

	// Chrome
	Идентификатор = "Chrome/";
	Позиция = СтрНайти(Строка, Идентификатор);
	Если Позиция > 0 Тогда
		Результат.Название = "Chrome";
		Строка = Сред(Строка, Позиция + СтрДлина(Идентификатор));
		Позиция = СтрНайти(Строка, " ");
		Если Позиция > 0 Тогда
			Строка = СокрЛ(Лев(Строка, Позиция - 1));
			Результат.Версия = Строка;
		КонецЕсли;
		Возврат Результат;
	КонецЕсли;

	// Safari
	Идентификатор = "Safari/";
	Если СтрНайти(Строка, Идентификатор) > 0 Тогда
		Результат.Название = "Safari";
		Идентификатор = "Version/";
		Позиция = СтрНайти(Строка, Идентификатор);
		Если Позиция > 0 Тогда
			Строка = Сред(Строка, Позиция + СтрДлина(Идентификатор));
			Позиция = СтрНайти(Строка, " ");
			Если Позиция > 0 Тогда
				Результат.Версия = СокрЛП(Лев(Строка, Позиция - 1));
			КонецЕсли;
		КонецЕсли;
		Возврат Результат;
	КонецЕсли;

	// Firefox
	Идентификатор = "Firefox/";
	Позиция = СтрНайти(Строка, Идентификатор);
	Если Позиция > 0 Тогда
		Результат.Название = "Firefox";
		Строка = Сред(Строка, Позиция + СтрДлина(Идентификатор));
		Если Не ПустаяСтрока(Строка) Тогда
			Результат.Версия = СокрЛП(Строка);
		КонецЕсли;
		Возврат Результат;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

Функция ТекущийКаталогПрограммы()
	
	#Если ВебКлиент Или МобильныйКлиент Тогда
		КаталогПрограммы = "";
	#Иначе
		КаталогПрограммы = КаталогПрограммы();
	#КонецЕсли
	
	Возврат КаталогПрограммы;
	
КонецФункции

Функция РазрешениеОсновногоЭкрана()
	
	ИнформациюЭкрановКлиента = ПолучитьИнформациюЭкрановКлиента();
	Если ИнформациюЭкрановКлиента.Количество() > 0 Тогда
		DPI = ИнформациюЭкрановКлиента[0].DPI; // АПК:1353 - не требуется перевод на русский язык.
		РазрешениеОсновногоЭкрана = ?(DPI = 0, 72, DPI);
	Иначе
		РазрешениеОсновногоЭкрана = 72;
	КонецЕсли;
	
	Возврат РазрешениеОсновногоЭкрана;
	
КонецФункции

Функция ИдентификаторКлиента()
	
	СистемнаяИнформация = Новый СистемнаяИнформация;
	Возврат СистемнаяИнформация.ИдентификаторКлиента;
	
КонецФункции

Функция ЭтоВебКлиент()
	
#Если ВебКлиент Тогда
	Возврат Истина;
#Иначе
	Возврат Ложь;
#КонецЕсли
	
КонецФункции

Функция ЭтоМобильныйКлиент()
	
#Если МобильныйКлиент Тогда
	Возврат Истина;
#Иначе
	Возврат Ложь;
#КонецЕсли
	
КонецФункции

// Возвращаемое значение:
//   см. ОбщегоНазначения.СистемнаяИнформацияКлиента
//
Функция СистемнаяИнформацияКлиента()
	
	Результат = Новый Структура(
		"ВерсияОС,
		|ВерсияПриложения,
		|ИдентификаторКлиента,
		|ИнформацияПрограммыПросмотра,
		|ОперативнаяПамять,
		|Процессор,
		|ТипПлатформы");
	
	СистемнаяИнформация = Новый СистемнаяИнформация;
	ЗаполнитьЗначенияСвойств(Результат, СистемнаяИнформация);
	Результат.ТипПлатформы = ОбщегоНазначенияКлиентСервер.ИмяТипаПлатформы(СистемнаяИнформация.ТипПлатформы);
	
	Возврат Новый ФиксированнаяСтруктура(Результат);
	
КонецФункции

#КонецОбласти

// Продолжение процедуры НачатьВыполнениеОбработкиОповещения.
//
// Параметры:
//  Размер - Число
//  Контекст - Структура:
//   * Оповещение - ОписаниеОповещения
//   * Результат  - Произвольный
//
Процедура НачатьВыполнениеОбработкиОповещенияЗавершение(Размер, Контекст) Экспорт
	
	ВыполнитьОбработкуОповещения(Контекст.Оповещение, Контекст.Результат);
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Вспомогательные процедуры и функции.

Процедура ВойтиВОбластьДанных()
	
	Если ПустаяСтрока(ПараметрЗапуска) Тогда
		Возврат;
	КонецЕсли;
	
	ПараметрыЗапуска = СтрРазделить(ПараметрЗапуска, ";", Ложь);
	
	Если ПараметрыЗапуска.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	ЗначениеПараметраЗапуска = ВРег(ПараметрыЗапуска[0]);
	
	Если ЗначениеПараметраЗапуска <> ВРег("ВойтиВОбластьДанных") Тогда
		Возврат;
	КонецЕсли;
	
	Если ПараметрыЗапуска.Количество() < 2 Тогда
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'В параметре запуска %1 дополнительно укажите значение разделителя (число).'"),
			"ВойтиВОбластьДанных");
	КонецЕсли;
	
	Попытка
		ЗначениеРазделителя = Число(ПараметрыЗапуска[1]);
	Исключение
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Значением разделителя в параметре %1 должно быть число.'"),
			"ВойтиВОбластьДанных");
	КонецПопытки;
	
	СтандартныеПодсистемыВызовСервера.ВойтиВОбластьДанных(ЗначениеРазделителя);
	
КонецПроцедуры

// Обновляет параметры работы клиента после очередной интерактивной обработки при запуске.
Процедура ОбновитьПараметрыРаботыКлиента(Параметры, ПервыйВызов = Ложь, ОбновитьПовторноИспользуемыеЗначения = Истина)
	
	Если ПервыйВызов Тогда
		ИмяПараметра = "СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы";
		Если ПараметрыПриложения[ИмяПараметра] = Неопределено Тогда
			ПараметрыПриложения.Вставить(ИмяПараметра, Новый Структура);
		КонецЕсли;
		ИмяПараметра = "СтандартныеПодсистемы.ЗапускПрограммыЗавершен";
		Если ПараметрыПриложения[ИмяПараметра] = Неопределено Тогда
			ПараметрыПриложения.Вставить(ИмяПараметра, Ложь);
		КонецЕсли;
	ИначеЕсли Параметры.КоличествоПолученныхПараметровКлиента = Параметры.ПолученныеПараметрыКлиента.Количество() Тогда
		Возврат;
	КонецЕсли;
	
	Параметры.Вставить("КоличествоПолученныхПараметровКлиента", Параметры.ПолученныеПараметрыКлиента.Количество());
	
	ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"].Вставить(
		"ПолученныеПараметрыКлиента", Параметры.ПолученныеПараметрыКлиента);
	
	Если ОбновитьПовторноИспользуемыеЗначения Тогда
		ОбновитьПовторноИспользуемыеЗначения();
	КонецЕсли;
	
КонецПроцедуры

// Проверяет результат интерактивной обработки, если Отказ, тогда вызывает обработку завершения.
// Если добавлен новый полученный параметр клиента, обновляет параметры работы клиента.
//
// Параметры:
//   Параметры - см. ОбщегоНазначенияКлиентПереопределяемый.ПередНачаломРаботыСистемы.Параметры.
//
// Возвращаемое значение:
//   Булево - Истина, если можно продолжить выполнения, и соответственно, не выполнялся
//            обработчик оповещения, указанный в свойствах ОбработкаЗавершения.
//
Функция ПродолжитьДействияПередНачаломРаботыСистемы(Параметры)
	
	Если Параметры.Отказ Тогда
		ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения);
		Возврат Ложь;
	КонецЕсли;
	
	ОбновитьПараметрыРаботыКлиента(Параметры);
	
	Возврат Истина;
	
КонецФункции

// Обрабатывает ошибку, найденную при вызове обработчика события ПриНачалеРаботыСистемы.
//
// Параметры:
//   Параметры          - см. ОбщегоНазначенияКлиентПереопределяемый.ПриНачалеРаботыСистемы.Параметры.
//   ИнформацияОбОшибке - ИнформацияОбОшибке - информация об ошибке.
//   ПрекратитьРаботу   - Булево - если указано Истина, то при ошибке запуска не будет возможности продолжить работу.
//
Процедура ОбработатьОшибкуПередНачаломРаботыСистемы(Параметры, ИнформацияОбОшибке, ПрекратитьРаботу = Ложь)
	
	ОбработатьОшибкуПриЗапускеИлиЗавершении(Параметры, ИнформацияОбОшибке, "Запуск", ПрекратитьРаботу);
	
КонецПроцедуры

// Проверяет результат обработчика события ПередНачаломРаботыСистемы и выполняет обработчик оповещения.
//
// Параметры:
//   Параметры - см. ОбщегоНазначенияКлиентПереопределяемый.ПередНачаломРаботыСистемы.Параметры.
//
// Возвращаемое значение:
//   Булево - Истина, если был выполнен обработчик оповещения, указанный
//            ОбработкаЗавершения ОбработкаЗавершения или запланирован переход к выполнению
//            интерактивной обработке, указанной в свойстве ИнтерактивнаяОбработка.
//
Функция ИнтерактивнаяОбработкаПередНачаломРаботыСистемы(Параметры)
	
	ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"];
	
	Если Параметры.ИнтерактивнаяОбработка = Неопределено Тогда
		Если Параметры.Отказ Тогда
			ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения);
			Возврат Истина;
		КонецЕсли;
		Возврат Ложь;
	КонецЕсли;
	
	ОбновитьПараметрыРаботыКлиента(Параметры);
	
	Если НЕ Параметры.НепрерывноеВыполнение Тогда
		ИнтерактивнаяОбработка = Параметры.ИнтерактивнаяОбработка;
		Параметры.ИнтерактивнаяОбработка = Неопределено;
		УстановитьПоследнююПроцедуру(Параметры,,, ИнтерактивнаяОбработка);
		ВыполнитьОбработкуОповещения(ИнтерактивнаяОбработка, Параметры);
		
	Иначе
		// Требуется подготовка к выполнению интерактивной обработки, затребованной
		// в процессе выполнения обработчика ПередНачаломРаботыСистемы, которая
		// предполагает скрытие рабочего стола и обновление интерфейса перед
		// продолжением при первом вызове процедуры ПриНачалеРаботыСистемы.
		ПараметрыПриЗапускеПрограммы.Вставить("ПараметрыОбработки", Параметры);
		СкрытьРабочийСтолПриНачалеРаботыСистемы();
		ПараметрыПриЗапускеПрограммы.Вставить("ПропуститьОчисткуСкрытияРабочегоСтола");
		
		Если Параметры.ОповещениеЗавершения = Неопределено Тогда
			// Вызов процедуры ПередНачаломРаботыСистемы выполнен платформой,
			// как обработчика события, до открытия главного окна 1С:Предприятия 8.
			Если Не ОтключенаЛогикаНачалаРаботыСистемы() Тогда
				УстановитьПараметрыФункциональныхОпцийИнтерфейсаПриЗапуске();
			КонецЕсли;
		Иначе
			// Вызов процедуры ПередНачаломРаботыСистемы выполнен программно, как вход в область данных,
			// поэтому продолжение после обновления интерфейса возможно только через обработчик ожидания.
			ПодключитьОбработчикОжидания("ОбработчикОжиданияПриНачалеРаботыСистемы", 0.1, Истина);
		КонецЕсли;
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

Процедура УстановитьПоследнююПроцедуру(Параметры, ИмяМодуля = "", ИмяПроцедуры = "", ОписаниеОповещения = Неопределено)
	
	Если ОписаниеОповещения = Неопределено Тогда
		Параметры.МодульПоследнейПроцедуры = ИмяМодуля;
		Параметры.ИмяПоследнейПроцедуры = ИмяПроцедуры;
	Иначе
		Параметры.МодульПоследнейПроцедуры = ОписаниеОповещения.Модуль;
		Параметры.ИмяПоследнейПроцедуры = ОписаниеОповещения.ИмяПроцедуры;
	КонецЕсли;
	
КонецПроцедуры

Функция ПолноеИмяПоследнейПроцедурыПередНачаломРаботыСистемы() Экспорт
	
	Свойства = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"];
	Если Свойства = Неопределено
	 Или Не Свойства.Свойство("ПараметрыОбработкиПередНачаломРаботыСистемы") Тогда
		Возврат "";
	КонецЕсли;
	Параметры = Свойства.ПараметрыОбработкиПередНачаломРаботыСистемы;
	
	Если ТипЗнч(Параметры.МодульПоследнейПроцедуры) = Тип("ОбщийМодуль") Тогда
		ИменаКлиентскихМодулей = СтандартныеПодсистемыВызовСервера.ИменаКлиентскихМодулей();
		Для Каждого ИмяКлиентскогоМодуля Из ИменаКлиентскихМодулей Цикл
			Попытка
				ТекущийМодуль = ОбщегоНазначенияКлиент.ОбщийМодуль(ИмяКлиентскогоМодуля);
			Исключение
				ТекущийМодуль = Неопределено;
			КонецПопытки;
			Если ТекущийМодуль = Параметры.МодульПоследнейПроцедуры Тогда
				ИмяМодуля = ИмяКлиентскогоМодуля;
				Прервать;
			КонецЕсли;
		КонецЦикла;
	ИначеЕсли ТипЗнч(Параметры.МодульПоследнейПроцедуры) = Тип("ФормаКлиентскогоПриложения") Тогда
		ИмяМодуля = Параметры.МодульПоследнейПроцедуры.ИмяФормы;
	Иначе
		ИмяМодуля = Строка(Параметры.МодульПоследнейПроцедуры);
	КонецЕсли;
	
	Возврат Строка(ИмяМодуля) + "." + Параметры.ИмяПоследнейПроцедуры;
	
КонецФункции

// Проверяет результат интерактивной обработки, если Отказ, тогда вызывает обработку завершения.
//
// Параметры:
//   Параметры - см. ОбщегоНазначенияКлиентПереопределяемый.ПриНачалеРаботыСистемы.Параметры.
//
// Возвращаемое значение:
//   Булево - Истина, если можно продолжить выполнения, и соответственно, не выполнялся
//            обработчик оповещения, указанный в свойствах ОбработкаЗавершения.
//
Функция ПродолжитьДействияПриНачалеРаботыСистемы(Параметры)
	
	Если Параметры.Отказ Тогда
		ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения);
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

// Обрабатывает ошибку, найденную при вызове обработчика события ПриНачалеРаботыСистемы.
//
// Параметры:
//   Параметры          - см. ОбщегоНазначенияКлиентПереопределяемый.ПриНачалеРаботыСистемы.Параметры.
//   ИнформацияОбОшибке - ИнформацияОбОшибке - информация об ошибке.
//   ПрекратитьРаботу   - Булево - если указано Истина, то при ошибке запуска не будет возможности продолжить работу.
//
Процедура ОбработатьОшибкуПриНачалеРаботыСистемы(Параметры, ИнформацияОбОшибке, ПрекратитьРаботу = Ложь)
	
	ОбработатьОшибкуПриЗапускеИлиЗавершении(Параметры, ИнформацияОбОшибке, "Запуск", ПрекратитьРаботу);
	
КонецПроцедуры

// Проверяет результат обработчика события ПриНачалеРаботыСистемы и выполняет обработчик оповещения.
//
// Параметры:
//   Параметры - см. ОбщегоНазначенияКлиентПереопределяемый.ПриНачалеРаботыСистемы.Параметры.
//
// Возвращаемое значение:
//   Булево - Истина, если был выполнен обработчик оповещения, указанный в
//            свойствах ОбработкаЗавершения или ИнтерактивнаяОбработка.
//
Функция ИнтерактивнаяОбработкаПриНачалеРаботыСистемы(Параметры)
	
	Если Параметры.ИнтерактивнаяОбработка = Неопределено Тогда
		Если Параметры.Отказ Тогда
			ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения);
			Возврат Истина;
		КонецЕсли;
		Возврат Ложь;
	КонецЕсли;
	
	ИнтерактивнаяОбработка = Параметры.ИнтерактивнаяОбработка;
	
	Параметры.НепрерывноеВыполнение = Ложь;
	Параметры.ИнтерактивнаяОбработка = Неопределено;
	
	ВыполнитьОбработкуОповещения(ИнтерактивнаяОбработка, Параметры);
	
	Возврат Истина;
	
КонецФункции

Функция ВыполняетсяИнтерактивнаяОбработкаПередНачаломРаботыСистемы()
	
	Если ПараметрыПриложения = Неопределено Тогда
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Возникла непредвиденная ситуация при запуске программы.
			           |
			           |Техническая информация:
			           |Недопустимый вызов %1 при запуске программы. Сначала должна быть завершена процедура %2.'"),
			"СтандартныеПодсистемыКлиент.ПриНачалеРаботыСистемы",
			"СтандартныеПодсистемыКлиент.ПередНачаломРаботыСистемы");
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;	

	ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"]; // Структура
	Если Не ПараметрыПриЗапускеПрограммы.Свойство("ПараметрыОбработки") Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Параметры = ПараметрыПриЗапускеПрограммы.ПараметрыОбработки;
	УстановитьПоследнююПроцедуру(Параметры, "СтандартныеПодсистемыКлиент",
		"ВыполняетсяИнтерактивнаяОбработкаПередНачаломРаботыСистемы");
	Если Параметры.ИнтерактивнаяОбработка = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	
	ПодключитьОбработчикОжидания("ОбработчикОжиданияНачатьИнтерактивнуюОбработкуПередНачаломРаботыСистемы", 0.1, Истина);
	Параметры.НепрерывноеВыполнение = Ложь;
	
	Возврат Истина;
	
КонецФункции

Процедура НачатьИнтерактивнуюОбработкуПередНачаломРаботыСистемы() Экспорт
	
	ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"]; // Структура
	
	Параметры = ПараметрыПриЗапускеПрограммы.ПараметрыОбработки;
	ИнтерактивнаяОбработка = Параметры.ИнтерактивнаяОбработка;
	Параметры.ИнтерактивнаяОбработка = Неопределено;
	УстановитьПоследнююПроцедуру(Параметры,,, ИнтерактивнаяОбработка);
	
	ВыполнитьОбработкуОповещения(ИнтерактивнаяОбработка, Параметры);
	
	ПараметрыПриЗапускеПрограммы.Удалить("ПараметрыОбработки");
	
КонецПроцедуры

Функция ИнтерактивнаяОбработкаПередЗавершениемРаботыСистемы(Параметры)
	
	Если Параметры.ИнтерактивнаяОбработка = Неопределено Тогда
		Если Параметры.Отказ Тогда
			ВыполнитьОбработкуОповещения(Параметры.ОбработкаЗавершения);
			Возврат Истина;
		КонецЕсли;
		Возврат Ложь;
	КонецЕсли;
	
	Если Не Параметры.НепрерывноеВыполнение Тогда
		ИнтерактивнаяОбработка = Параметры.ИнтерактивнаяОбработка;
		Параметры.ИнтерактивнаяОбработка = Неопределено;
		ВыполнитьОбработкуОповещения(ИнтерактивнаяОбработка, Параметры);
		
	Иначе
		// Выполнен вызов из обработчика события ПередЗавершениемРаботыСистемы для подготовки
		// выполнения интерактивной обработки через обработчик ожидания.
		ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"].Вставить("ПараметрыОбработкиЗавершения", Параметры);
		Параметры.НепрерывноеВыполнение = Ложь;
		ПодключитьОбработчикОжидания(
			"ОбработчикОжиданияИнтерактивнаяОбработкаПередЗавершениемРаботыСистемы", 0.1, Истина);
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

// Выводит форму сообщений пользователю при закрытии программы, либо выводит сообщение.
Процедура ОткрытьФормуПредупрежденийПриЗавершенииРаботы(Параметры)
	
	ДополнительныеПараметры = Новый Структура;
	ДополнительныеПараметры.Вставить("ВариантФормы", "Вопрос");
	
	ОбработкаОтвета = Новый ОписаниеОповещения("ПослеЗакрытияФормыПредупрежденийПриЗавершенииРаботы",
		ЭтотОбъект, ДополнительныеПараметры);
		
	Предупреждения = Параметры.Предупреждения;
	Параметры.Удалить("Предупреждения");
	
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("Предупреждения", Предупреждения);
	
	ИмяФормы = "ОбщаяФорма.ПредупрежденияПриЗавершенииРаботы";
	
	Если Предупреждения.Количество() = 1 И ПустаяСтрока(Предупреждения[0].ТекстФлажка) Тогда
		ДополнительныеПараметры.Вставить("ВариантФормы", "ПрикладнаяФорма");
		ОткрытьПрикладнуюФормуПредупреждения(Параметры, ОбработкаОтвета, Предупреждения[0], ИмяФормы, ПараметрыФормы);
	Иначе	
		ДополнительныеПараметры.Вставить("ВариантФормы", "СтандартнаяФорма");
		ПараметрыОткрытияФормы = Новый Структура;
		ПараметрыОткрытияФормы.Вставить("ИмяФормы", ИмяФормы);
		ПараметрыОткрытияФормы.Вставить("ПараметрыФормы", ПараметрыФормы);
		ПараметрыОткрытияФормы.Вставить("ОбработкаОтвета", ОбработкаОтвета);
		ПараметрыОткрытияФормы.Вставить("РежимОткрытияОкна", Неопределено);
		Параметры.ИнтерактивнаяОбработка = Новый ОписаниеОповещения(
			"ИнтерактивнаяОбработкаПредупрежденийПриЗавершенииРаботы", ЭтотОбъект, ПараметрыОткрытияФормы);
	КонецЕсли;
	
КонецПроцедуры

// Продолжение процедуры ОткрытьФормуПредупрежденийПриЗавершенииРаботы.
Процедура ИнтерактивнаяОбработкаПредупрежденийПриЗавершенииРаботы(Параметры, ПараметрыОткрытияФормы) Экспорт
	
	ОткрытьФорму(
		ПараметрыОткрытияФормы.ИмяФормы,
		ПараметрыОткрытияФормы.ПараметрыФормы, , , , ,
		ПараметрыОткрытияФормы.ОбработкаОтвета,
		ПараметрыОткрытияФормы.РежимОткрытияОкна);
	
КонецПроцедуры

// Продолжение процедуры ПоказатьПредупреждениеИПродолжить.
Процедура ПоказатьПредупреждениеИПродолжитьЗавершение(Результат, Параметры) Экспорт
	
	Если Результат <> Неопределено Тогда
		Если Результат.Значение = "Завершить" Тогда
			Параметры.Отказ = Истина;
		ИначеЕсли Результат.Значение = "Перезапустить" Или Результат.Значение = КодВозвратаДиалога.Таймаут Тогда
			Параметры.Отказ = Истина;
			Параметры.Перезапустить = Истина;
		КонецЕсли;
	КонецЕсли;
	ВыполнитьОбработкуОповещения(Параметры.ОбработкаПродолжения);
	
КонецПроцедуры

// Формирует отображение одного вопроса.
//
//	Если в ПредупреждениеПользователю есть свойство "ТекстГиперссылки", то открывается "ФормаИндивидуальногоОткрытия" из
//	Структуры вопроса.
//	Если в ПредупреждениеПользователю есть свойство "ТекстФлажка", то открывается форма
//	"ОбщаяФорма.ВопросПередЗавершениемРаботыСистемы".
//
// Параметры:
//  Параметры - см. СтандартныеПодсистемыКлиент.ПараметрыДействийПередЗавершениемРаботыСистемы.
//  ОбработкаОтвета - ОписаниеОповещения - для продолжения после получения ответа пользователя.
//  ПредупреждениеПользователю - см. СтандартныеПодсистемыКлиент.ПредупреждениеПриЗавершенииРаботы.
//  ИмяФормы - Строка - имя общей формы с вопросами.
//  ПараметрыФормы - Структура - параметры для формы с вопросами.
//
Процедура ОткрытьПрикладнуюФормуПредупреждения(Параметры, ОбработкаОтвета, ПредупреждениеПользователю, ИмяФормы, ПараметрыФормы)
	
	ТекстГиперссылки = "";
	Если НЕ ПредупреждениеПользователю.Свойство("ТекстГиперссылки", ТекстГиперссылки) Тогда
		Возврат;
	КонецЕсли;
	Если ПустаяСтрока(ТекстГиперссылки) Тогда
		Возврат;
	КонецЕсли;
	
	ДействиеПриНажатииГиперссылки = Неопределено;
	Если НЕ ПредупреждениеПользователю.Свойство("ДействиеПриНажатииГиперссылки", ДействиеПриНажатииГиперссылки) Тогда
		Возврат;
	КонецЕсли;
	
	ДействиеГиперссылка = ПредупреждениеПользователю.ДействиеПриНажатииГиперссылки;
	Форма = Неопределено;
	
	Если ДействиеГиперссылка.Свойство("ПрикладнаяФормаПредупреждения", Форма) Тогда
		ПараметрыФормы = Неопределено;
		Если ДействиеГиперссылка.Свойство("ПараметрыПрикладнойФормыПредупреждения", ПараметрыФормы) Тогда
			Если ТипЗнч(ПараметрыФормы) = Тип("Структура") Тогда 
				ПараметрыФормы.Вставить("ЗавершениеРаботыПрограммы", Истина);
			ИначеЕсли ПараметрыФормы = Неопределено Тогда 
				ПараметрыФормы = Новый Структура;
				ПараметрыФормы.Вставить("ЗавершениеРаботыПрограммы", Истина);
			КонецЕсли;
			
			ПараметрыФормы.Вставить("ЗаголовокКнопкиДа",  НСтр("ru = 'Завершить'"));
			ПараметрыФормы.Вставить("ЗаголовокКнопкиНет", НСтр("ru = 'Отмена'"));
			
		КонецЕсли;
		ПараметрыОткрытияФормы = Новый Структура;
		ПараметрыОткрытияФормы.Вставить("ИмяФормы", Форма);
		ПараметрыОткрытияФормы.Вставить("ПараметрыФормы", ПараметрыФормы);
		ПараметрыОткрытияФормы.Вставить("ОбработкаОтвета", ОбработкаОтвета);
		ПараметрыОткрытияФормы.Вставить("РежимОткрытияОкна", ДействиеГиперссылка.РежимОткрытияОкна);
		Параметры.ИнтерактивнаяОбработка = Новый ОписаниеОповещения(
			"ИнтерактивнаяОбработкаПредупрежденийПриЗавершенииРаботы", ЭтотОбъект, ПараметрыОткрытияФормы);
		
	ИначеЕсли ДействиеГиперссылка.Свойство("Форма", Форма) Тогда 
		ПараметрыФормы = Неопределено;
		Если ДействиеГиперссылка.Свойство("ПараметрыФормы", ПараметрыФормы) Тогда
			Если ТипЗнч(ПараметрыФормы) = Тип("Структура") Тогда 
				ПараметрыФормы.Вставить("ЗавершениеРаботыПрограммы", Истина);
			ИначеЕсли ПараметрыФормы = Неопределено Тогда 
				ПараметрыФормы = Новый Структура;
				ПараметрыФормы.Вставить("ЗавершениеРаботыПрограммы", Истина);
			КонецЕсли;
		КонецЕсли;
		ПараметрыОткрытияФормы = Новый Структура;
		ПараметрыОткрытияФормы.Вставить("ИмяФормы", Форма);
		ПараметрыОткрытияФормы.Вставить("ПараметрыФормы", ПараметрыФормы);
		ПараметрыОткрытияФормы.Вставить("ОбработкаОтвета", ОбработкаОтвета);
		ПараметрыОткрытияФормы.Вставить("РежимОткрытияОкна", ДействиеГиперссылка.РежимОткрытияОкна);
		Параметры.ИнтерактивнаяОбработка = Новый ОписаниеОповещения(
			"ИнтерактивнаяОбработкаПредупрежденийПриЗавершенииРаботы", ЭтотОбъект, ПараметрыОткрытияФормы);
		
	КонецЕсли;
	
КонецПроцедуры

// Если указан ПрекратитьРаботу = Истина, то прервать дальнейшее выполнение клиентского кода и прекратить работу.
//
Процедура ОбработатьОшибкуПриЗапускеИлиЗавершении(Параметры, ИнформацияОбОшибке, Событие, ПрекратитьРаботу = Ложь)
	
	Если Событие = "Запуск" Тогда
		Если ПрекратитьРаботу Тогда
			Параметры.Отказ = Истина;
			Параметры.ОбработкаПродолжения = Параметры.ОбработкаЗавершения;
		КонецЕсли;
	Иначе
		Параметры.ОбработкаПродолжения = Новый ОписаниеОповещения(
			"ДействияПередЗавершениемРаботыСистемыПослеОбработкиОшибки", ЭтотОбъект, Параметры.ОбработкаПродолжения);
	КонецЕсли;
	
	СтандартныеПодсистемыВызовСервера.ЗаписатьОшибкуВЖурналРегистрацииПриЗапускеИлиЗавершении(
		ПрекратитьРаботу, Событие, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));	
		
	ТекстПредупреждения = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке) + Символы.ПС + Символы.ПС
		+ НСтр("ru = 'Техническая информация записана в журнал регистрации.'");
		
	Если Событие = "Запуск" И ПрекратитьРаботу Тогда
		ТекстПредупреждения = НСтр("ru = 'Запуск программы невозможен:'")
			+ Символы.ПС + Символы.ПС + ТекстПредупреждения;
	КонецЕсли;
	
	ИнтерактивнаяОбработка = Новый ОписаниеОповещения("ПоказатьПредупреждениеИПродолжить", ЭтотОбъект, ТекстПредупреждения);
	Параметры.ИнтерактивнаяОбработка = ИнтерактивнаяОбработка;
	
КонецПроцедуры

Процедура УстановитьПараметрыФункциональныхОпцийИнтерфейсаПриЗапуске()
	
	ПараметрыПриЗапускеПрограммы = ПараметрыПриложения["СтандартныеПодсистемы.ПараметрыПриЗапускеПрограммы"];
	
	Если ТипЗнч(ПараметрыПриЗапускеПрограммы) <> Тип("Структура")
	 Или Не ПараметрыПриЗапускеПрограммы.Свойство("ОпцииИнтерфейса") Тогда
		// Обработка ошибки запуска.
		Возврат;
	КонецЕсли;
	
	Если ПараметрыПриЗапускеПрограммы.Свойство("ОпцииИнтерфейсаУстановлены") Тогда
		Возврат;
	КонецЕсли;
	
	ОпцииИнтерфейса = Новый Структура(ПараметрыПриЗапускеПрограммы.ОпцииИнтерфейса);
	
	// Установка параметров функциональных опций производится только тогда, когда они заданы.
	Если ОпцииИнтерфейса.Количество() > 0 Тогда
		УстановитьПараметрыФункциональныхОпцийИнтерфейса(ОпцииИнтерфейса);
	КонецЕсли;
	
	ПараметрыПриЗапускеПрограммы.Вставить("ОпцииИнтерфейсаУстановлены");
	
КонецПроцедуры

Функция ТребуетсяПоказРекомендацииПоОбъемуОперативнойПамяти()
	ПараметрыКлиента = ПараметрыРаботыКлиентаПриЗапуске();
	Возврат ПараметрыКлиента.ТребуетсяПоказРекомендацииПоОбъемуОперативнойПамяти;
КонецФункции

Процедура ОповеститьОНехваткеПамяти() Экспорт
	РекомендуемыйОбъем = ПараметрыРаботыКлиентаПриЗапуске().РекомендуемыйОбъемОперативнойПамяти;
	
	Заголовок = НСтр("ru = 'Скорость работы снижена'");
	Текст = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Рекомендуется увеличить объем памяти до %1 Гб.'"), РекомендуемыйОбъем);
	
	ПоказатьОповещениеПользователя(Заголовок, 
		"e1cib/app/Обработка.РекомендацияПоПовышениюСкоростиРаботы",
		Текст, БиблиотекаКартинок.Предупреждение32, СтатусОповещенияПользователя.Важное);
КонецПроцедуры

Процедура ОповещениеТекущегоПользователяОПредстоящемПерезапуске(СекундДоПерезапуска) Экспорт

	ВремяПерезапуска = СтандартныеПодсистемыВызовСервера.ВремяПерезапускаПриложенияДляПримененияИсправлений();
	ВремяПерезапуска = ?(ВремяПерезапуска <> Неопределено, Формат(ВремяПерезапуска,"ДФ=HH:mm"),
		Формат(ОбщегоНазначенияКлиент.ДатаСеанса() + СекундДоПерезапуска, "ДФ=HH:mm"));
	ТекстЗаголовка = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Перезапуск приложения в %1'"), ВремяПерезапуска);
	ТекстСообщения = НСтр("ru = 'Ранее был запланирован перезапуск приложения для применения исправлений. Нажмите здесь, чтобы отложить.'");
	ПоказатьОповещениеПользователя(
		ТекстЗаголовка,
		"e1cib/app/ОбщаяФорма.КонтрольДинамическогоОбновления",
		ТекстСообщения, БиблиотекаКартинок.Предупреждение32,
		СтатусОповещенияПользователя.Важное,
		"ПерезапускПриложенияСегодня");

КонецПроцедуры
	
Процедура ПодключениеОбработчиковОжиданияПоказаОповещенийИПерезапуска(СекундДоПерезапуска) Экспорт
	ПодключитьОбработчикОжидания("ОповещениеОПредстоящемПерезапускеЗаПятьМинут", СекундДоПерезапуска - 300, Истина);
	ПодключитьОбработчикОжидания("ОповещениеОПредстоящемПерезапускеЗаТриМинуты", СекундДоПерезапуска - 180, Истина);
	ПодключитьОбработчикОжидания("ОповещениеОПредстоящемПерезапускеЗаМинуту", СекундДоПерезапуска - 60, Истина);
	ПодключитьОбработчикОжидания("ПерезапускПриложения", СекундДоПерезапуска, Истина);
КонецПроцедуры 

Процедура ОтключитьЗапланированныйПерезапуск() Экспорт
	ОтключитьОбработчикОжидания("ОповещениеОПредстоящемПерезапускеЗаПятьМинут");
	ОтключитьОбработчикОжидания("ОповещениеОПредстоящемПерезапускеЗаТриМинуты");
	ОтключитьОбработчикОжидания("ОповещениеОПредстоящемПерезапускеЗаМинуту");
	ОтключитьОбработчикОжидания("ПерезапускПриложения");
КонецПроцедуры

#КонецОбласти
